CrendKing / avisynth_filter

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

How to implement DirectShow filter graph and custom video renderer #88

Closed vle07 closed 11 months ago

vle07 commented 11 months ago

I'm developing a VR video player, and need some help with setting up a DirectShow filter graph to work with LAV filters, vapoursynth/avisynth, and a custom video renderer (ultimately with the goal of being able to use SVP with the VR video player). I create the vapoursynth/avisynth filter by using CoCreateInstance with CLSID "{e5e2c1a6-c90f-4247-8bf5-604fb180a932}" or "{3ab7506b-fc4a-4144-8ee3-a97fab4f9cb3}" (I believe those are the UUIDs for the CSynthFilter class). I connect that filter inbetween the LAV video decoder and my custom video renderer (derived from CBaseVideoRenderer). When I open a video file that's less than 30fps, the video plays correctly. However, when I enable SVP or when I open a 60fps video (without SVP running), I get an IMediaEvent with an EC_ERRORABORT event code that specifies a VFW_E_TYPE_NOT_ACCEPTED error code. I put a breakpoint on my video renderer input pin's CheckMediaType function, and it seems like everything is working fine, since it's able to return S_OK when stepping through the code (the media type is FORMAT_VideoInfo2 with NV12 compression).

I'm kind of stumped on how to proceed with fixing the issue. Am I setting up the filter graph and vapoursynth/avisynth filters correctly? Are there specific things I need to implement with the video renderer filter and its input pin in order for vapoursynth to work with SVP? Do I need to wait for or respond to specific IMediaEvents? If you have any suggestions, it'd be greatly appreciated!

Edit: I've attached some log files.

The 30fps video without svp running works fine. avisynth_filter_30fps_no_svp.log

The 30 fps video with svp running starts ok with some decoded frames before SVP can kick in, but then reloadscript from auxilary frameserver gets called, The output pin attempts to reconnect, but this time all the results return 0, which causes the error "Downstream does not accept any of the new output media types". avisynth_filter_30fps_with_svp.log

The 60fps video without svp running initially connects with media type nv12. However, reloadscript from auxilary frameserver gets called, The output pin attempts to reconnect, but this time all the results return 0, which causes the error "Downstream does not accept any of the new output media types". avisynth_filter_60fps_no_svp.log

Seems like I need to figure out how to properly reconnect the output pins with the media type. My video renderer's input pin does not get its "CheckMediaType" function called on the reconnect. The input pin inherits from CRendererInputPin. I wonder if I need to modify something more.

CrendKing commented 11 months ago

Since your base class (that w/o SVP) is working, it seems LAV and our filter is working. Since it has problem once involving SVP, I guess it might has something to do with how your built the graph, or there's something you do that SVP doesn't like. And since MPC-HC/BE works when the combination of our filter + SVP works, it is doable.

I suggest you ask help from clsid2, or chainikdn. If you are sure there is a bug in our filter, please provide reproducible steps.

vle07 commented 11 months ago

Since your base class (that w/o SVP) is working, it seems LAV and our filter is working. Since it has problem once involving SVP, I guess it might has something to do with how your built the graph, or there's something you do that SVP doesn't like. And since MPC-HC/BE works when the combination of our filter + SVP works, it is doable.

I suggest you ask help from clsid2, or chainikdn. If you are sure there is a bug in our filter, please provide reproducible steps.

I updated my original post with some log files. I think my video renderer's input pin's checkmediatype function isn't being called on reconnect. Do you have any idea what I would need to modify? The input pin derives from CRendererInputPin, and just overrides the CheckMediaType function as well as the GetAllocator function which returns VFW_E_NO_ALLOCATOR, so the upstream filters can provide the allocator. 60fps videos without svp running also have the issue.

Edit: It's also possible I have vapoursynth improperly installed. I kind of assumed that if mpv and mpc-hc were working with vapoursynth and svp, then it's already installed on my system, and I can just use the CLSID of the vapoursynth filter to create the vapoursynth filter and it would just work. Maybe I need to use the vapoursynth.dll file to create the filter instead? Or maybe I'm missing the vapoursynth pyd files so the scripts aren't loading properly?

vle07 commented 11 months ago

Alright, turns out I need to override the video renderer pin's ReceiveConnection function to allow it to connect to a pin even when it's already connected or running. The video starts flickering green when I enable SVP, but I probably just need to spend time figuring out how to deal with the media samples after the reconnection.

CrendKing commented 11 months ago

Interesting. I have no experience on video renderer implementation. Hope you can figure everything out!