Log in

View Full Version : DirectShow filter as Avisynth source (other than ffdshow)?


Pages : 1 [2]

chainik_svp
16th August 2020, 10:40
what I personally know at this point is it works in ffdshow
and it definitely will be necessary for SVP to work correctly

+++
ConvertToYUV420()
ConvertBits(10)
doesn't work - the filter won't attach to the graph
only works with ConvertBits(16)

CrendKing
17th August 2020, 07:28
I'll try the dynamic format change in ffdshow see how's it work.

About the ConvertBits(10) issue, I actually have a discussion with AviSynthPlus guys at https://github.com/AviSynth/AviSynthPlus/issues/146. Basically, both the P010 and P016 types are internally represented as CS_YUV420P16 in AviSynth. Therefore the filter only supports converting CS_YUV420P16 back to P010.

ConvertBits(10) converts the format to CS_YUV420P10. Because there is no format for it to convert to, the filter disconnects from the graph. However, since P010 is basically P016 with 6 bits padded as 0, there is no downside of always using ConvertBits(16).

ffdshow only supports limited number of output types, and 10 bits and 16 bits compressed formats are not among them. All these are converted to NV12, which cause the picture to have green artifacts.

My reasoning of only supporting the few popular AviSynth formats is that AviSynth already has a excellent set of convert functions (http://avisynth.nl/index.php/Convert). It is much easier for user to add a line of ConvertXXX() at the end of the script, than reimplement those convert functions in the filter again. Plus the mapping between DirectShow media types and AviSynth formats are not one-to-one mapping. Here's some examples:


AviSynth CS_YV12 can be losslessly converted to NV12, YV12, I420 or IYUV. Which one should be right output type?
Both P010 and P016 are represented as AviSynth CS_YUV420P16.
How to convert CS_YUV9 to a reasonable DirectShow type? Do we choose a 4:1:1 format such as NV11 or a 4:2:0 format such as NV12? What if NV11 is less lossy but the renderer does not support it?

chainik_svp
17th August 2020, 08:47
> It is much easier for user to add a line of ConvertXXX()

still P010 is the most popular format for high bit depth video, e.g. 4K/HDR, why adding _unnecessary_ conversion P010->P016?
besides, EVR renderer doesn't seems to work with P016 o_O

> Plus the mapping between DirectShow media types and AviSynth formats are not one-to-one mapping. Here's some examples:
> Which one should be right output type?

the one that needs less work

===
re-read that "Does AviSynth+ internally support P010?" conversation... :)
so the problem is the filter gets left-shifted pixels from a decoder? in this case doing a conversion to "true" P010 would be an extra step, I agree
I was just confused because in mpv and VLC, P010 is "true" P010, w/o this "microsoft-specific"...

+++
when working in P010, EVR renderer won't load for some reason

CrendKing
17th August 2020, 19:42
> still P010 is the most popular format for high bit depth video, e.g. 4K/HDR, why adding _unnecessary_ conversion P010->P016?
> I was just confused because in mpv and VLC, P010 is "true" P010, w/o this "microsoft-specific"...

Basically it is a incompatibility between AviSynth and Microsoft. AviSynth treats CS_YUV420P10 as little-endian P010, where Microsoft treats as big-endian. You can imagine that we can write some function to traverse every 16 bits of the buffer and flip the endian to truly support the P010 in AviSynth, but is it really worth the effort and performance cost? P010 is P016 with 6 bits of zero. There is no conversion.

> besides, EVR renderer doesn't seems to work with P016 o_O

It shouldn't be a problem. Here is how my filter works with formats. Basically there are sets of mappings from {DS input type} -> {AviSynth format} -> {DS output type}. During pin connection, the filter will supply all compatible pairs of mappings that shares the same intermediate AviSynth format to upstream and downstream. And upstream/downstream can choose whichever they support/prefer to complete the connection.

Take CS_YUV420P16 as example. In DS side, it can be either P010 or P016. So if upstream wants to connect with P016 but downstream wants P010, that's completely fine. P010 -> CS_YUV420P16 -> P016 also works. The only thing it does not work out of the box is something like NV12 -> ??? -> P016. In this case, I'll have to ask the user to put a ConvertP016() at the end of their script.

BTW, I just make quite some changes for the dynamic format thingy. Could you try https://github.com/CrendKing/avisynth_filter/releases/tag/0.5.5? I verified the MVC scenario you mentioned should be working now.

chainik_svp
17th August 2020, 20:58
Regarding EVR - no idea why it won't attach to the graph when avisynth_filter is enabled. It definitely works with simple P010 source -> EVR config, but doesn't like P010 source -> avs (P010) -> EVR. Basic VMR is selected instead, and it doesn't work either, producing corrupted image.

> I verified the MVC scenario you mentioned should be working now.

Seems to work when switching from double frame to mono, but still crashes switching from 1920*1080 to 1920*2160

clsid
17th August 2020, 23:36
P010/P016 does not work well with EVR/VMR renderers. Use NV12 instead. You should output P010/P016 only when connecting to madVR or MPCVR.

Example code from LAV:
https://github.com/clsid2/LAVFilters/blob/master/decoder/LAVVideo/LAVVideo.cpp#L1064

CrendKing
18th August 2020, 00:01
About the EVR issue:
https://i.imgur.com/7Y5rQTU.jpg

About mono to double:
https://streamable.com/crghkh

Used script:

AvsFilterSource()
return Info()

CrendKing
18th August 2020, 00:02
P010/P016 does not work well with EVR/VMR renderers. Use NV12 instead. You should output P010/P016 only when connecting to madVR or MPCVR.

If needed, user can always tick off the P010 and P016 formats in the option page if they use EVR/VMR. It will automatically fallback to NV12.

chainik_svp
18th August 2020, 10:24
regarding MVC:
doesn't crash with
AvsFilterSource()
return Info()
crashes with
AvsFilterSource()
crop(8,8,-8,-8)
return Info()

regarding EVR: dunno, I can't make it work o_O MPC-HC 1.9.6 if it matters...

+++
upd: EVR-CP works in MPC-BE, doesn't work in MPC-HC

+++
const REFERENCE_TIME frameTime = frameNb * llMulDiv(_videoInfo.fps_denominator, UNITS, _videoInfo.fps_numerator, 0);
return _frameHandler.GetNearestFrame(frameTime);

not sure it will work for variable frame rate videos

CrendKing
18th August 2020, 21:38
Crash: Just updated the repo. Should be working now. Let me know if you want to test it out. I can send you compiled files.

EVR: In my end, with MPC-HC, the pin just connects with NV12 format, no crash. Could it be related to video? Here's some log for pin connection:

MPC-BE

T 6324 @ 0: CAviSynthFilter::CAviSynthFilter()
T 6324 @ 6: Add acceptable input definition: 0
T 6324 @ 6: Add acceptable output definition: 0
T 6324 @ 6: Add compatible definitions: input 0 output 0
T 6324 @ 6: Add acceptable output definition: 1
T 6324 @ 6: Add compatible definitions: input 0 output 1
T 6324 @ 6: Add acceptable output definition: 2
T 6324 @ 6: Add compatible definitions: input 0 output 2
T 6324 @ 6: Add acceptable output definition: 3
T 6324 @ 6: Add compatible definitions: input 0 output 3
T 6324 @ 6: Reject input definition due to settings: 6
T 6324 @ 6: Reject input definition due to settings: 9
T 6324 @ 8: Add acceptable input definition: 4
T 6324 @ 8: Add acceptable output definition: 4
T 6324 @ 8: Add compatible definitions: input 4 output 4
T 6324 @ 8: Add acceptable output definition: 5
T 6324 @ 8: Add compatible definitions: input 4 output 5
T 6324 @ 8: Reject input definition due to settings: 5
T 6324 @ 8: Accept input definition: 0
T 6324 @ 8: Accept input definition: 0
T 6324 @ 8: Connected input pin with definition: 0
T 6324 @ 8: Offer output definition: 0
T 6324 @ 8: Offer output definition: 1
T 6324 @ 8: Offer output definition: 2
T 6324 @ 8: Offer output definition: 3
T 6324 @ 8: Offer output definition: 4
T 6324 @ 8: Offer output definition: 5
T 6324 @ 8: Offer output definition: 0
T 6324 @ 8: Offer output definition: 1
T 6324 @ 8: Offer output definition: 2
T 6324 @ 8: Offer output definition: 3
T 6324 @ 8: Offer output definition: 4
T 6324 @ 9: Offer output definition: 5
T 6324 @ 9: CAviSynthFilter::CAviSynthFilter()
T 6324 @ 14: Offer output definition: 0
T 6324 @ 14: Accept transform: out 0
T 6324 @ 14: Accept transform: out 0
T 6324 @ 18: Offer output definition: 1
T 6324 @ 18: Accept transform: out 1
T 6324 @ 18: Accept transform: out 1
T 6324 @ 18: Offer output definition: 2
T 6324 @ 18: Accept transform: out 2
T 6324 @ 18: Accept transform: out 2
T 6324 @ 18: Offer output definition: 3
T 6324 @ 18: Accept transform: out 3
T 6324 @ 18: Accept transform: out 3
T 6324 @ 18: Offer output definition: 4
T 6324 @ 18: Accept transform: out 4
T 6324 @ 18: Accept transform: out 4
T 6324 @ 18: Offer output definition: 5
T 6324 @ 18: Accept transform: out 5
T 6324 @ 18: Accept transform: out 5
T 6324 @ 99: Offer output definition: 0
T 6324 @ 99: Accept transform: out 0
T 6324 @ 99: Accept transform: out 0
T 6324 @ 99: Accept transform: out 0
T 6324 @ 109: Connected with types: in 0 out 0


MPC-HC

T 16700 @ 1: CAviSynthFilter::CAviSynthFilter()
T 16700 @ 19: Add acceptable input definition: 4
T 16700 @ 19: Add acceptable output definition: 4
T 16700 @ 19: Add compatible definitions: input 4 output 4
T 16700 @ 19: Add acceptable output definition: 5
T 16700 @ 19: Add compatible definitions: input 4 output 5
T 16700 @ 19: Reject input definition due to settings: 5
T 16700 @ 19: Reject input definition due to settings: 5
T 16700 @ 23: Add acceptable input definition: 0
T 16700 @ 23: Add acceptable output definition: 0
T 16700 @ 23: Add compatible definitions: input 0 output 0
T 16700 @ 23: Add acceptable output definition: 1
T 16700 @ 23: Add compatible definitions: input 0 output 1
T 16700 @ 23: Add acceptable output definition: 2
T 16700 @ 23: Add compatible definitions: input 0 output 2
T 16700 @ 23: Add acceptable output definition: 3
T 16700 @ 23: Add compatible definitions: input 0 output 3
T 16700 @ 23: Reject input definition due to settings: 6
T 16700 @ 23: Reject input definition due to settings: 6
T 16700 @ 23: Reject input definition due to settings: 7
T 16700 @ 23: Reject input definition due to settings: 7
T 16700 @ 23: Reject input definition due to settings: 9
T 16700 @ 23: Reject input definition due to settings: 9
T 16700 @ 23: Reject input definition due to settings: 8
T 16700 @ 23: Reject input definition due to settings: 8
T 16700 @ 23: Reject input definition due to settings: 10
T 16700 @ 23: Reject input definition due to settings: 10
T 16700 @ 23: Accept input definition: 4
T 16700 @ 23: Accept input definition: 4
T 16700 @ 23: Connected input pin with definition: 4
T 16700 @ 24: Offer output definition: 4
T 16700 @ 24: Offer output definition: 5
T 16700 @ 24: Offer output definition: 0
T 16700 @ 24: Offer output definition: 1
T 16700 @ 24: Offer output definition: 2
T 16700 @ 24: Offer output definition: 3
T 16700 @ 24: CAviSynthFilter::CAviSynthFilter()
T 16700 @ 192: Offer output definition: 4
T 16700 @ 192: Accept transform: out 4
T 16700 @ 192: Accept transform: out 4
T 16700 @ 192: Offer output definition: 5
T 16700 @ 192: Accept transform: out 5
T 16700 @ 192: Accept transform: out 5
T 16700 @ 192: Offer output definition: 0
T 16700 @ 192: Accept transform: out 0
T 16700 @ 192: Accept transform: out 0
T 16700 @ 209: Offer output definition: 4
T 16700 @ 209: Offer output definition: 5
T 16700 @ 209: Offer output definition: 0
T 16700 @ 209: Offer output definition: 1
T 16700 @ 209: Offer output definition: 2
T 16700 @ 209: Offer output definition: 3
T 16700 @ 209: Reconnect with types: old in 4 new in 0 out 0
T 16700 @ 209: Accept transform: out 0
T 16700 @ 209: Accept transform: out 0
T 16700 @ 209: Reject input definition due to settings: 5
T 16700 @ 209: Reject input definition due to settings: 5
T 16700 @ 210: Reject input definition due to settings: 6
T 16700 @ 210: Reject input definition due to settings: 6
T 16700 @ 210: Reject input definition due to settings: 7
T 16700 @ 210: Reject input definition due to settings: 7
T 16700 @ 210: Reject input definition due to settings: 9
T 16700 @ 210: Reject input definition due to settings: 9
T 16700 @ 210: Reject input definition due to settings: 8
T 16700 @ 210: Reject input definition due to settings: 8
T 16700 @ 210: Reject input definition due to settings: 10
T 16700 @ 210: Reject input definition due to settings: 10
T 16700 @ 210: Accept input definition: 0
T 16700 @ 210: Accept transform: out 0
T 16700 @ 210: Accept input definition: 0
T 16700 @ 210: Connected with types: in 0 out 0


Notice for MPC-HC, there is the "Reconnect with types: old in 4 new in 0 out 0". Format 4 is P010. 0 is NV12. As to why such different behavior, maybe clsid has some idea?

Variable frame rate video: I don't have any experience about this. Do you have any sample video? How does ffdshow behave? Does it treat like dynamic format change?

###################

By the way, since you know about SVP, I have a question. When I put SVSmoothFps_NVOF() in script, and NOT recreate the avs environment every time I connect pin or seek, the filter just freezes. If I do recreate, everything works line. I have a little comment about it in filter.cpp. However, the SVSuper() -> SVAnalyse() -> SVSmoothFps() triplet works regardless of recreating or not. Does SVSmoothFps_NVOF() internally have some sort of restriction that it can be only eval'd once? Like there's some singleton predicate?

clsid
18th August 2020, 21:38
MPC-HC/LAV has a workaround to disable use of P010/P016 when it is (potentially) unsupported. It only allows P010 on recent versions of Windows 10.

chainik_svp
18th August 2020, 22:09
> Variable frame rate video: I don't have any experience about this.

You'll have different frame durations for different frames :)
So your method of getting frame time from frame number, based on a fixed frame duration, will fail - it'll return wrong frames.
You need to count input frames, and return the exact frame (by number) when it's requested.

> Do you have any sample video?

Basically any anime video out there is VFR in some parts.

> How does ffdshow behave? Does it treat like dynamic format change?

It's not a format change. Since ffdshow works with frame numbers it doesn't have any problems here.

> When I put SVSmoothFps_NVOF() in script, and NOT recreate the avs environment every time I connect pin or seek, the filter just freezes.

I'll take a look...

chainik_svp
19th August 2020, 14:18
I wonder if it's really necessary to reload script so many times?
Considering the simple YV12 playback, it's reloaded:
- 4 times in CheckConnect
- 1 time in HandleInputFormatChange
- 1 time in TransformAndDeliver

total of six (6) times just to start the playback, plus one time for every set on pause (why??).

And each time SVSmoothFps have to init and destroy OpenCL context, queues, build shader programs etc., plus init/destoy CUDA context for NVOF.

I'd at least remove Reset() from pause handler... 5 times re-init is better than 6 :D

===

The "NVOF problem" - my guess is it arises from the fact that when reloading script w/o deleting the environment, the "new" filters initialization might occur before destruction of "old" filters.

chainik_svp
19th August 2020, 21:17
Regarding VFR. Just played with an anime file where frame rate is constantly floating between 24 and 30 fps, and found that IMediaSample::GetTime() is returning incorrect end-time - it's always equal to start-time plus average-time-per-frame defined in VIDEOINFOHEADER. However subtracting previous frame's start-time from the current frame's start-time gives correct value.

CrendKing
20th August 2020, 06:38
clsid: Thanks for info. However I tested in the latest Windows 10 (ver 2004) though. My MPC-HC version is 1.9.4.21 (daeb8bf8d).

VFR: "You need to count input frames, and return the exact frame (by number) when it's requested." But you are assuming the samples we receive are ordered and continuous. Upstream can give us frame #X then #X + 2 in case of frame drop. And if seek happens, all we know is the time of that frame. Why does avs take frame number instead of frame time? Does that mean avs only support CFR?

I also played a VFR video (where ffmpeg vfrdet reports "VFR:0.501632 (1076/1069) min: 3753 max: 15015 avg: 3777"). I don't see any problem during playback.

Reload: You can read my comment in filter.cpp. I hate reloading. It destroys performance. But I think every single one of them is necessary.

CheckConnect: Reason why reload is to feed the script new input format. Each time the upstream gives me a new media type. I need to run through the script to get the corresponding output format, then feed it to downstream. Good news is these reload only reload the script, not the whole avs environment (because there is no frame generated yet).

HandleInputFormatChange: Same reason as above. New input media type, thus reload. Bad news, since the playback is already started, there could be frames inside avs. To flush the cache, we need to reload the whole thing. Maybe one day we will get some answer from https://github.com/AviSynth/AviSynthPlus/issues/180.

TransformAndDeliver: This is for Pause(). As you may know, the DirectShow document (https://docs.microsoft.com/en-us/windows/win32/directshow/flushing) specifically requires filters to "discard any samples that were created before the seek command". We could flush cached frames in our filter, but we can't control any caching in avs. Thus a full reload is done every time user seeks. You could argue that it is not strictly "necessary", but then you will encounter the same ghost frame problem as in ffdshow, that after seeking you still see a bunch of frames around the time before seeking. I'd rather the seek taking a bit of time than seeing wrong frames.

NVOF: You are correct full reload works. The first 5 reloads (being full or not) are not the concern because they are generally not user visible (usually one time per playback). However, if every time we completely reload the environment there is no problem. But doing full reload in Pause() will impose unbearable latency for seeking. So either AviSynth gives us proper flushing method, NVOF somehow can do without full reload, or use NVOF with ghost frame.

chainik_svp
20th August 2020, 08:34
> Thus a full reload is done every time user seeks.

seek != pause

> I don't see any problem during playback.

and still you
1. fetch the wrong frames using fixed frameTime value while converting requested frame number to timestamp
2. pass a cfr sequence to downstream

CrendKing
20th August 2020, 11:03
> Thus a full reload is done every time user seeks.

seek != pause

Fixed and pushed.


> I don't see any problem during playback.

and still you
1. fetch the wrong frames using fixed frameTime value while converting requested frame number to timestamp
2. pass a cfr sequence to downstream

I get what you are saying, but I don't understand how to reconcile between DS and AVS. From what I see (http://avisynth.nl/index.php/VFR), AVS only supports CFR, otherwise it would not use frame number to getFrame(). So feeding any VFR to AVS would only get out CFR. Am I wrong?

chainik_svp
20th August 2020, 13:40
> So feeding any VFR to AVS would only get out CFR. Am I wrong?

you feed AVS with a frame sequence and you get another frame sequence back, it's up to you how to set timestamps
what I know is ffdshow somehow managed to deal with VFR input/output

https://github.com/jeeb/ffdshow-tryouts/blob/422a13650bb3d3c986e21e3abad210e7d815ebdf/src/imgFilters/avisynth/TimgFilterAvisynth.cpp#L975

CrendKing
20th August 2020, 23:01
I get it now. Basically we need to calculate the output frame duration ourselves, by applying the avs scaling (where the scaling itself is fixed at e.g. 2x, 1.5x, etc) to the source frame duration. And to get the frame number, we need to count from start or last seek point, instead of relying on the average frame duration, which is just a statistic number and rather meaningless. And for seeking, I don't need to care about anything before seeking. Just rebuild the frame queue from anew.

edcrfv94
28th November 2020, 13:03
VapourSynth multithreading stable than AviSynth, maybe supporting VapourSynth is a better idea.

real.finder
28th November 2020, 16:42
VapourSynth multithreading stable than AviSynth, maybe supporting VapourSynth is a better idea.

not anymore, I don't see any problem in multithreading stablety in AviSynth+ 3.6.2-test4 20201112

CrendKing
29th November 2020, 14:45
VapourSynth multithreading stable than AviSynth, maybe supporting VapourSynth is a better idea.

Do you mean AviSynth is not stable in general, or specifically in this filter's use case? If latter, can you open an issue in the repo so I can understand the problem.

Technically I could create a version of this filter that uses VapourSynth instead of AviSynth as the frame server (I have a working internal version but extremely buggy, not actively working on it), but since it pulls in Python in runtime thus way heavier in footprint, I need some good use case and incentive to do that work.

edcrfv94
2nd December 2020, 04:27
Do you mean AviSynth is not stable in general, or specifically in this filter's use case? If latter, can you open an issue in the repo so I can understand the problem.

Technically I could create a version of this filter that uses VapourSynth instead of AviSynth as the frame server (I have a working internal version but extremely buggy, not actively working on it), but since it pulls in Python in runtime thus way heavier in footprint, I need some good use case and incentive to do that work.

My computer is currently unavailable.
Currently, VapourSynth HDB support and multithreading are much better than AviSynth+.
You can try some complex script with multithreading e.g: QTGMC + fslg_quick_denoise + mcDAA3.

real.finder
2nd December 2020, 07:02
My computer is currently unavailable.
Currently, VapourSynth HDB support and multithreading are much better than AviSynth+.
You can try some complex script with multithreading e.g: QTGMC + fslg_quick_denoise + mcDAA3.

I do use complex scripts (using QTGMC, mcDAA3 and others) most of times and I can say that there are no problem these days in avs+ mt

HDB support maybe not as the vs one since there are few plugins need to add HBD in avs+, but again it's way better than 2019, since https://github.com/Asd-g?tab=repositories did added a lot since then

CrendKing
3rd December 2020, 19:49
Also remember that since the use case here is real-time video playing, having complex script that requires significant CPU time would jeopardize your experience. For instance, playing a 60 fps video means you can't spend more than 16.6ms per frame on both decoding, avs and rendering, or you will start to drop frames. So essentially we only need to concern about a very subset of functionality. As long as this subset is stable, it's fine.

cork_OS
5th December 2020, 14:10
Hello.
I've faced several problems with AVSF, not sure where to report it.
1. On the new PC manually installed AVSF didn't appear in the player's filters list (and don't work) until activate_remote_control.reg is applied. Is it a bug or a feature?

2. Player hangs on start if this script is loaded:
AvsFilterSource()
TDecimate(mode=2, rate=23.976)
prefetch()
If TDecimate string is commented on player start and uncommented after playback starts, the video with script reloaded in real-time runs ok (audio sync not tested).

3. QTGMC and ApparentFPS work great individually, but not in one script.
This script plays choppy, but seeking works:
AvsFilterSource()
QTGMC()
ApparentFPS()
prefetch()
This script plays smoothly, but player hangs on seek:
AvsFilterSource()
QTGMC()
prefetch()
ApparentFPS()

AVS+ 3.6.1, AVSF 0.8.2. TDecimate problem tested on two PCs with different players/renderers (MPC-HC+madVR/MPC-BE+EVR-CP).

StainlessS
5th December 2020, 17:36
I cant remember what AvsFilterSource() is, but suggest RequestFramesLinear() [with appropriate cache args] inserted after AvsFilterSource.
Before and After cache args might best be at least the framerate of the source clip. [maybe]

EDIT: or maybe if still probs, try at least the framerate of the source clip * Prefetch.

EDIT: Note, ApparentFPS() has to access 2*FrameRate [by default] frames everytime you jump about, hence hang
especially due to QTGMC doing its stuff for each of those.

EDIT: ApparentFPS() wil need linear access, need set as such in your SetMTMode.avs thing. [MT_SERIALIZED]
so probably best placed AFTER Prefetch().

CrendKing
6th December 2020, 11:05
Hello.
I've faced several problems with AVSF, not sure where to report it.


Please report to https://github.com/CrendKing/avisynth_filter/issues/new/choose. There is bug report template to ask you information I need.

1. On the new PC manually installed AVSF didn't appear in the player's filters list (and don't work) until activate_remote_control.reg is applied. Is it a bug or a feature?

There are other people report installation not working. Some were due to lack of Visual C++ runtime. activate_remote_control.reg should have nothing to do with it. If it's true, it's bug. Please report and we track there.

2. Player hangs on start if this script is loaded:

I thought "Prefetch" has required thread number argument. Have you tried adding it?

I've tested FDecimate2 before, but never tested TDecimate. Please report on separate issue.

However, we should first solve the installation issue. I'm not even sure you are actually loaded the filter in its expected state.

This script plays smoothly, but player hangs on seek:

I thought "prefetch" must be the last statement in a script. Am I wrong? Reference: http://avisynth.nl/index.php/AviSynth%2B:
You enable MT by placing a single call to Prefetch(X) at the end of your script, where X is the number of threads to use.

I cant remember what AvsFilterSource() is

It is the source function added by this filter: https://github.com/CrendKing/avisynth_filter#avsfiltersource. It feeds source samples from upstream DirectShow filter to AviSynth engine.

StainlessS
6th December 2020, 17:04
I thought "Prefetch" has required thread number argument. Have you tried adding it?
Prefetch has a default value, which is number of Physical CPUs + 1.

NOTE, I think 'Physical CPUs' is meaning 'Physical Cores'.
Eg, a machine might have 2 physical Xeon CPUs, each with 6 physical cores and 6 logical cores, 12 physical [EDIT: total] cores per CPU, or
24 threads/cores total machine.
Dont know if Physical_CPUs means physical_cores in single CPU, or eg total number of physical cores in multi CPU Xeon system.
From Avisynth.cpp


size_t __stdcall ScriptEnvironment::GetProperty(AvsEnvProperty prop)
{
switch(prop)
{
case AEP_FILTERCHAIN_THREADS:
return (prefetcher != NULL) ? prefetcher->NumPrefetchThreads()+1 : 1;
case AEP_PHYSICAL_CPUS:
return GetNumPhysicalCPUs();
case AEP_LOGICAL_CPUS:
return std::thread::hardware_concurrency();
case AEP_THREAD_ID:
return 0;
case AEP_THREADPOOL_THREADS:
return thread_pool->NumThreads();
case AEP_VERSION:
return AVS_SEQREV;
default:
this->ThrowError("Invalid property request.");
return std::numeric_limits<size_t>::max();
}

assert(0);
}


Also see GetProperty in avisynth.h

EDIT: Not available for Avs Standard v2.60 (dont know about v2.61).

I thought "prefetch" must be the last statement in a script.
Prefetch() is just an pretty standard filter which takes as its first argument a video clip,
it is more usually called with implicit Last clip, it also returns a video clip, and has never had to be final filter in script,
although that has been its usual use in the past.

I'm pretty sure that there was a Pinterf post [which I did not find] that showed multiple use of Prefetch in single script,
multi-use was quite recent mod to avs+. [EDIT: I only searched Devs forum, maybe was in Usage]

Quote by Pinterf, [cant directly quote a closed thread any more ???]:- https://forum.doom9.org/showthread.php?p=1904672#post1904672

Prefetch (clip c, int threads, int "frames")

In the original Plus, you could use only one Prefetch, but you can use any number of CUDA versions.
Also, an argument has been added to specify the number of frames to prefetch.
Prefetch (1,4) # Make 1 thread stand and prefetch 4 frames
By doing so, flexible parallelization configuration is possible, such as pipeline parallelization.

threads
Number of threads. If it is 0, it passes without doing anything.

frames
Number of frames to prefetch.
Again, if it is 0, it passes without doing anything.

Note above clip c,
and threads default = physical cores + 1, frames default is presumably 1 [although defaults tend not to be shown]

EDIT: Threads is Optional, should be enclosed in double quotes.

Prefetch (clip c, int "threads"=Physical_cores+1, int "frames"=1) # returning video clip

EDIT: I'm guessin that Physical_Cores might mean physical cores in a single CPU.

It is the source function added by this filter
Thanks.

clsid
6th December 2020, 18:00
There are other people report installation not working. Some were due to lack of Visual C++ runtime.I really recommend to use static linking. Pretty much every DirectShow filter uses static linking. Requiring runtimes is really annoying for distribution and also a support nightmare.

CrendKing
6th December 2020, 19:01
I really recommend to use static linking. Pretty much every DirectShow filter uses static linking. Requiring runtimes is really annoying for distribution and also a support nightmare.

Good suggestion. I didn't bother to change the default from Visual Studio. Now you mention it, next version will be statically linked.

CrendKing
7th December 2020, 05:06
2. Player hangs on start if this script is loaded:

The reason why it hangs is because the plugin tries to get frame on it own whenever the script is imported. However, the filter needs to import script during initialization phase to determine video info, when the source samples are not yet available. It becomes a chicken egg problem.

I could make it not hang by providing fake empty frame during initialization, and switch to real frame after, but I think you might be better just use FDecimate2 instead, if that's an option. I can give you a test build if you want.

cork_OS
7th December 2020, 14:55
I could make it not hang by providing fake empty frame during initialization, and switch to real frame after, but I think you might be better just use FDecimate2 instead, if that's an option. I can give you a test build if you want.
Unfortunately, FDecimate2 fails in my very simple 1-in-5 case where TDecimate instead works perfectly with default settings. Additionally, TDecimate has a very informative display (debug) mode. So it would be great to make AVSF TDecimate compatible. However, if requesting a frame on filter initialization is bad practice, maybe it's better to ask pinterf to fix TDecimate instead?

EDIT: ApparentFPS() wil need linear access, need set as such in your SetMTMode.avs thing. [MT_SERIALIZED]
so probably best placed AFTER Prefetch().
I've added SetFilterMTMode("ApparentFPS", MT_SERIALIZED) string to script, nothing changed.

CrendKing
7th December 2020, 18:04
requesting a frame on filter initialization is bad practice

It's not necessarily bad practice, because for conventional avs usage the source video file is probably always available. It is just not very compatible with the video playing use case.

You can try https://github.com/CrendKing/avisynth_filter/files/5653636/AviSynthFilter.zip if that fixes the TDecimate problem. It shouldn't hang, and I can see FPS change to 24, but I can't guarantee if every part of TDecimate is working properly.

I'll tend to the other one later. Maybe you can submit an issue for tracking purpose?

cork_OS
7th December 2020, 20:53
You can try https://github.com/CrendKing/avisynth_filter/files/5653636/AviSynthFilter.zip if that fixes the TDecimate problem. It shouldn't hang, and I can see FPS change to 24, but I can't guarantee if every part of TDecimate is working properly.
Thanks, it works.
Interestingly, TDecimate injected into SVP generated script doesn't hang with the previous AVSF version.
I'll tend to the other one later. Maybe you can submit an issue for tracking purpose?
Sure, I'll do it now.

StainlessS
7th December 2020, 23:15
I've added SetFilterMTMode("ApparentFPS", MT_SERIALIZED) string to script, nothing changed.
Yeh, and how bout RequestFramesLinear() ?

sappyyy
16th October 2021, 10:26
Here's autohotkey code to control - switch on/off - avisynthfilter from the player. PotPlayer taken as an example, replace with your .avs path,
remote control should be enabled


StrPutVar(string, ByRef var, encoding)
{
; Ensure capacity.
VarSetCapacity( var, StrPut(string, encoding)
; StrPut returns char count, but VarSetCapacity needs bytes.
* ((encoding="utf-16"||encoding="cp1200") ? 2 : 1) )
; Copy or convert the string.
return StrPut(string, &var, encoding)
}


;-------------------------------------------------------------------------------
send_WM_COPYDATA(Code, Str, WinId) { ; send string via WM_COPYDATA
;-------------------------------------------------------------------------------
DetectHiddenWindows, On
avsfilter := WinExist(WinId)
VarSetCapacity(COPYDATASTRUCT, A_PtrSize * 3, 0)
NumPut(Code, COPYDATASTRUCT)
if Str > 0
{
Numput(StrPutVar(Str, Str, "cp0"), COPYDATASTRUCT, A_PtrSize)
NumPut(&Str, COPYDATASTRUCT, A_PtrSize * 2)
SendMessage, 0x4a, A_ScriptHwnd, &COPYDATASTRUCT,, ahk_id %avsfilter%
}
else
SendMessage, 0x4a, A_ScriptHwnd, &COPYDATASTRUCT,, ahk_id %avsfilter%
}


#IfWinActive, ahk_exe potplayermini64.exe
Q::
DetectHiddenWindows, On
potavsfilter := WinExist("ahk_class AvsFilterRemoteControlClass ahk_exe potplayermini64.exe")

if potavsstate != %potavsfilter%
{
potavstoggle = 0
Send_WM_COPYDATA(403,"C:\Progs\PotPlayer\AviSynth\work\pot.avs","ahk_class AvsFilterRemoteControlClass ahk_exe potplayermini64.exe")
potavsstate = %potavsfilter%
}
else
if potavstoggle = 1
{
potavstoggle = 0
Send_WM_COPYDATA(403,"C:\Progs\PotPlayer\AviSynth\work\pot.avs","ahk_class AvsFilterRemoteControlClass ahk_exe potplayermini64.exe")
potavsstate = %potavsfilter%
}
else
{
potavstoggle = 1
Send_WM_COPYDATA(403,0,"ahk_class AvsFilterRemoteControlClass ahk_exe potplayermini64.exe")
}
return

flossy_cake
3rd November 2022, 03:50
Is it possible to get the filepath of the video being played so that we can apply per-file/folder processing? I saw this question was asked earlier by chainik_svp but didn't see to have an answer, only this:

You can get filename yourself.

Enumerate filters in the graph, until you find first one that implements IFileSourceFilter interface. Then use that to query filename.

https://docs.microsoft.com/en-us/windows/win32/api/strmif/nn-strmif-ifilesourcefilter


Also here (https://drive.google.com/file/d/1WfW3yXmGhIvUCiexQGYD18gSiXRe2bze/view?usp=share_link) is a test clip 720x576 square pixels 1.25:1 according to MediaInfo and MadVR, but running it through CrendKing's Avisynth filter results in slightly squished 1.22:1 aspect & MadVR reporting 1.22:1 also.

edit: how it should look:

https://i.ibb.co/ckGsCqs/1.png

After Avisynth plugin with propShow():

https://i.ibb.co/zNLwTxL/2.png
https://i.ibb.co/TWTGRjf/3.png

CrendKing
10th November 2022, 03:16
Handled in GitHub. Should be fixed in v1.4.6.

flossy_cake
10th November 2022, 14:05
Thanks a lot. Looks like I'll be migrating all my scripts across and using Avisynth this way from now on :)

Here is a template for noobs like myself



# main.avs

AvsFilterSource() # replaces DirectShowSource() etc.

if (FindStr(AvsFilterGetSourcePath(), "Series\Comedy\(2001-2003) The Office") != 0){
Import("The Office.avs")
}
else if (FindStr(AvsFilterGetSourcePath(), "Series\Comedy\(2005-2007) Extras") != 0){
Import("Extras.avs")
}
else {
AvsFilterDisconnect()
}

# FindStr() is case-sensitive.


# The Office.avs
Subtitle("Now playing: The Office", last_frame=int(5*last.FrameRate)) # show for 5 seconds


# Extras.avs
Subtitle("Now playing: Extras", last_frame=int(5*last.FrameRate))


Then in CrendKing's Avisynth filter GUI point it to main.avs.

Note that resizing works differently now since the filter passes on aspect ratio metadata to the renderer. eg. no need to scale NTSC 4:3 720x480 to 720x540, but there may be an upcoming override for that to force square pixels for backwards compatibility with existing scripts (link (https://github.com/CrendKing/avisynth_filter/issues/81))

flossy_cake
11th November 2022, 09:27
Note that resizing works differently now since the filter passes on aspect ratio metadata to the renderer. eg. no need to scale NTSC 4:3 720x480 to 720x540, but there may be an upcoming override for that to force square pixels for backwards compatibility with existing scripts (link (https://github.com/CrendKing/avisynth_filter/issues/81))


Actually letting the renderer perform the DAR correction has an added benefit in that it allows deinterlacing to be performed by the renderer (eg. MadVR's film mode and DXVA deint). Whereas if the renderer already receives the aspect-corrected 720x540 from Avisynth, the field alignment is ruined and deinterlacing cannot be done after this point.

Although it would be possible to workaround it by instead performing the DAR correction manually in MadVR using its "screen config" setting, but this is a bit convoluted and would require making multiple "screen config" profiles in MadVR.

flossy_cake
11th November 2022, 10:17
Spoke too soon.

It seems the Avisynth frame counter resets to 0 every time we seek. This breaks a lot of things.

*sigh*

Hoping it can be fixed, but I'm not gonna get my hopes up.