CrendKing / avisynth_filter

DirectShow filters that put AviSynth and VapourSynth into video playing
MIT License
107 stars 8 forks source link

1.1.6 doesn't provide source FPS via RC #60

Closed chainikdn closed 2 years ago

chainikdn commented 2 years ago

Playing from youtube, SVP relies on AVSF's FPS value (API_MSG_GET_SOURCE_AVG_FPS). With 1.1.6 it gets nothing almost every time. Works every time with 1.1.5.

01:07:31.867 [I]: AVSF: found new player instance
01:07:31.907 [I]: AVSF: filters in use: LAV Splitter Source (internal) -> LAV Video Decoder (internal) -> * -> Enhanced Video Renderer (custom presenter)
01:07:31.908 [I]: AVSF: new video in mpc-hc64.exe (64-bit) [MPC-HC 1.9.13.21] on screen 0
01:07:31.909 [I]: Media: video looks like some kind of stream
01:07:31.909 [I]: Media: video 1280x720 [PAR 1.000] **at 0.000 fps** (via video player)
CrendKing commented 2 years ago

The current API_MSG_GET_CURRENT_INPUT_FPS returns the actual input FPS that AVSF receives from upstream. To estimate that, AVSF needs approx. one second of frames to calculate. So if you call that API immediately, you will get 0. This behavior is unchanged since the beginning. After one second, you can see the exact number (before * 1000) in the status page (first number in Frame rate).

I think the reason why you see intermittent problem on Youtube is that if the server doesn't send enough frames fast enough before SVP reaches a time point, since you are still getting 0, you just gave up and assuming it's 0. But if the server responds fast enough, there's no problem. My theory is that you should never have any problem on local video files (unless the hard drive is really really slow).

There could be two solutions. Either SVP keep polling until it gets a stable FPS, no matter how long it takes. SVP can delay the kick in time until it's ready. Or I can return the container FPS instead for the API. Or you prefer a hybrid where container FPS is used when actual FPS is not ready?

CrendKing commented 2 years ago

I'm testing just returning a flat 60 to that API. However, SVP sometimes still show 0 FPS in the notification area, and has these in log

15:57:45.453 [I]: Media: video 1920x1080 [PAR 1.000] at 0.000 fps (via video player)
15:57:45.464 [W]: Playback [dfacf69]: playing at double rate, source frame rate unknown
15:57:49.598 [I]: Playback [dfacf69]: source frame rate changed to 59.999

So I think there's something else going on.

chainikdn commented 2 years ago

and that "something else" appeared in 1.1.6

CrendKing commented 2 years ago

Hey, this is open sourced, so you can see I didn't change anything about AVSF between 1.1.5 and 1.1.6. Plus SVP is close sourced so I have no information of how you produced these log lines. Shouldn't you be the one trying to figure out what's going on?

You have the ability to compile the filter. You can replace that API value to 60 and check yourself.

chainikdn commented 2 years ago

so you can see I didn't change anything about AVSF between 1.1.5 and 1.1.6

I can see you moved _remoteControl->Start() to another place one more time, for example...

You can replace that API value to 60 and check yourself.

yes, when I put constant value into API_MSG_GET_SOURCE_AVG_FPS - then I got it in SVP obviously _sourceAvgFrameRate is not initialized now at the time SVP asking for it

chainikdn commented 2 years ago

you moved _remoteControl->Start() to another place one more time

and this is the reason

CrendKing commented 2 years ago

I can see you moved _remoteControl->Start() to another place one more time, for example...

You are not wrong, but I still don't understand the root cause. The new location happens earlier than before, so if we return constant for that FPS API, you only get value earlier. Why did it make worse for SVP? I assume there's another API that triggered the symptom, which has invalid value in the new location but good in the old.

chainikdn commented 2 years ago

The new location happens earlier than before

exactly. you now start RC before _sourceAvgFrameRate gets initialized in ReloadScript, so SVP gets zero fps value. there's a ~250ms gap between CompleteConnect() and Active() in case of youtube playback (only ~100 ms for local file)

CrendKing commented 2 years ago

That's good point. I made that change so that the video format don't need to be reloaded across stop -> play cycle. But then the script clip needs to be kept during stop. I'll partially revert that change.

Do you still need the container FPS instead of actual "estimated FPS" (in mpv term) be returned instead so that it guaranteed to be a positive constant?

chainikdn commented 2 years ago

API_MSG_GET_SOURCE_AVG_FPS is the containter fps. We're talking about it here, don't confuse with API_MSG_GET_CURRENT_INPUT_FPS.

CrendKing commented 2 years ago

https://github.com/CrendKing/avisynth_filter/commit/4550d1ef367b5fbf2eac46ac4a621e4c68f5f802