Setting AudioFlushCb and then calling DestroyPlayer can freeze Unity
Summary
Calling Dispose() without calling Stop(), or calling Stop() and then Dispose() immediately [as is done in MinimalPlayback.cs] will freeze Unity, if LibVLCAudioFlushCB is set to anything other than null. If you wait a little while after Stop() to call Dispose(), it's fine. If you don't set AudioCallbacks or you set LibVLCAudioFlushCB to null, that will also prevent the issue
Minimal project and steps to reproduce
- Clone this repo: https://gitlab.com/brisingre/vlc-unity-bugs
- Import a recent development version of VLC Unity (I can provide the specific one I'm using if needed)
- Open the "139 AudioFlushCb Freeze" scene
- Press play in Unity
- Press DestroyPlayerOnly or StopAndDestroyPlayer and Unity will freeze.
- You will have to process-kill Unity and it might complain for a while when you restart it
- Pressing Stop and waiting for a second will prevent the bug from happening
- If you set LibVLCAudioFlushCB to null (line 29 in AudioPlaybackDestroyPlayerFreeze.cs) that will also prevent the bug from happening
What is the current bug behavior?
Calling Dispose() without calling Stop(), or calling Stop() and then Dispose() immediately [as is done in MinimalPlayback.cs] will freeze Unity, if LibVLCAudioFlushCB is set to anything other than null.
What is the expected correct behavior?
I don't really know. You're supposed to call Stop() before Dispose(). It seems very plausible that you are supposed to wait for Stop() to finish before calling Dipose() too. If so, it is not wrong for VLC Unity to fail in some way when you don't. Still, doing it this way is fine 99% of the time, and it is how MinimalPlayback.cs does it, and a freeze is unnecessarily severe. I'd much rather just get an error in the console. Even a crash would be better than a freeze I think -- at least a crash would show up in the logfile.
Does it work on other plaforms? Does it work with the official VLC apps?
Right now VLC for Unity only supports one platform. Android soon! But I am not set up to test on it right now.
Environment
- OS: Windows
- Version 10 LTSC
- Device: PC
- LibVLC version and architecture 4.0.0 x64
- LibVLCSharp version Not quite sure how to check this, sorry.
- VLC Unity plugin 0.1.5
- Scripting backend used Mono
Possible fixes
Setting LibVLCAudioFlushCb to null doesn't seem like the end of the world. What's the worst that can happen -- cached audio keeps playing for a tenth of a second after I call stop()? Not exactly a fix but a decent-enough workaround...
Waiting for Stop to finish before Dispose gets called seems like the correct way to do this, but I am not sure how to do that in Unity. The issue here is that Dispose is often called when the GameObject is disposed of (it has to be, or the mediaPlayer will stay in memory and keep playing audio) and that often happens on application exit, and I'm not certain, in those circumstances, whether I can wait for the Stopped event to fire. It seems like a lot of important stuff will no longer exist by the time it does. On the other hand, if I was very careful about not calling any Unity stuff that's going to be null in that last Stopped event, and only calling Dispose(), perhaps it would work...
I could imagine that there is something I'm supposed to be doing in the AudioFlushCb that I am not doing, which would prevent this.
It is also possible that it would work to set AudioFlushCb to null immediately before calling Dispose(), which would mitigate some of the problems that come from not implementing it at all.