CrendKing / avisynth_filter

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

CSynthFilter::TraverseFiltersInGraph() fails if audio-only file source is in filter graph #89

Closed vle07 closed 7 months ago

vle07 commented 8 months ago

I have a filter graph that contains both a video-only file source and audio-only file source. CSynthFilter::TraverseFiltersInGraph() always runs into the audio-only file source first, and then tries to find the video output pin on that filter. That fails, and the function just exits without finding the video-only file source and its connected filters. This causes the VapourSynth Filter to not be listed, meaning SVP doesn't think VapourSynth is in the filter graph.

My filter graph is setup like this: LAV Splitter Source for video -> LAV Video Decoder -> VapourSynth -> Video Renderer LAV Splitter Source for audio -> LAV Audio Decoder -> Audio Renderer

Since the number of filters connected to the LAV Splitter for audio is less than the one for video, traversing the IGraphBuilder->EnumFilters list will always run into the LAV splitter for audio first. I've tried altering the order I add filters to the graph and connect them, but it doesn't seem like it's possible to get the video file source to be listed before the audio.

I suggest the entire filter graph should be traversed, and every file source filter should be examined for a video output pin. Rather than prematurely exiting the function on the first file source filter found.

CrendKing commented 8 months ago

Do you have a step-by-step instruction to reproduce the setup you have? Is it possible to do in MPC-BE/HC?

vle07 commented 8 months ago

You'll need to create a custom filter graph. I'm not sure if that's possible with MPC-BE/HC. Maybe you can do it with graphedt.exe (found in the Windows Kits bin folder in Program Files (x86)), though my graphedt.exe crashes whenever I try to look for DirectShow filters.

I use yt-dlp to retrieve download links for a youtube video. It comes in a separate video and audio stream. I then create a filter graph. Add a Lav Splitter Source filter, and use it to open the video url. Add a Lav Video Decoder filter, and connect it to the Lav Splitter Source. Add a VapourSynth filter, and connect it to the Lav Video Decoder. Add a video renderer (any should be fine), and connect it to the VapourSynth filter. Then I add another Lav Splitter Source filter to the same graph, and use it to open the audio url. Add a Lav Audio Decoder filter, and connect it to the Lav Splitter Source (that opened the audio url). Add an audio renderer (like DirectSound or any other audio renderer), and connect it to the Lav Audio Decoder.

If you run enumfilters on the resulting filter graph, you'll see that the LAV Splitter Source for the audio url always gets encountered before the LAV Splitter Source for the video url. This causes the CSynthFilter::TraverseFiltersInGraph() to only look at the LAV Splitter Source for the audio url, and when it can't find any video output pins on that source filter, it'll exit without looking at the rest of the filter graph. You can fix this issue by just allowing the function to continue examining the rest of the filters in the graph if no video output pins are found on a source filter.

CrendKing commented 8 months ago

Feel free to shoot a PR.

CrendKing commented 7 months ago

Close for inactivity.