MediaPlayer.Select() can crash Unity
Summary
If I call MediaPlayer.Select() on a track that isn't from that player's list of Tracks, my whole game crashes to desktop.
Minimal project and steps to reproduce
-
Make a new Unity project and import VLCUnity from the Package Manager. (Any unity version should do, but I am using 2020.3.6f1.)
-
Replace MinimalPlayback.cs with attached modified version. (This version is much more heavily modified than the one in my last report.) MinimalPlayback.cs
-
Open the MinimalPlayback scene.
-
Select the VLC Screen 1 object and set your path back to "http://commondatastorage.googleapis.com/gtv-videos-bucket/sample/BigBuckBunny.mp4"
-
SAVE YOUR SCENE
-
Press Play.
-
After a two second delay, "ThisFunctionIsFine()" should appear in the log. Nothing bad should happen.
-
Edit the AudioCrashTest() function in MinimalPlayback.cs. Comment out ThisFunctionIsFine() [line 35] and uncomment ThisFunctionWillCrash() [line 36]
-
SAVE YOUR SCENE
-
Press Play.
-
After a two second delay, the editor will crash to desktop
-
Restart the editor and reopen the scene if necessary.
-
Edit the AudioCrashTest() function in MinimalPlayback.cs. Comment out ThisFunctionWillCrash() [line 36] and uncomment ThisFunctionWillNotCrash() [line 37]
-
SAVE YOUR SCENE
-
Press Play.
-
After a two second delay, "ThisFunctionWillNotCrash()" and an error saying "Cannot switch to track: " should appear in the log.
Here's the interesting part of the modified MinimalPlayback.cs script, for reference.
#region Audio Crash Tests
IEnumerator AudioCrashTest()
{
yield return new WaitForSeconds(2); //Can't set audio tracks until playback starts, we'll just be lazy and give it 2 seconds to start
ThisFunctionIsFine(); //Sets the audio track from _mediaPlayer.Tracks
//ThisFunctionWillCrash(); //Sets the audio track from _mediaPlayer.Media.TrackList
//ThisFunctionWillNotCrash(); //Checks if the audio track will crash. If it will, instead of switching to it and crashing, just log an error message.
}
void ThisFunctionIsFine()
{
Debug.Log("ThisFunctionIsFine()");
var track = _mediaPlayer.Tracks(TrackType.Audio)[0]; //Select the first audio track from the MediaPlayer
_mediaPlayer.Select(track); //Switch to it
}
void ThisFunctionWillCrash()
{
Debug.Log("ThisFunctionWillCrash()");
var track = _mediaPlayer.Media.TrackList(TrackType.Audio)[0]; //Select the first audio track from MediaPlayer.Media
_mediaPlayer.Select(track); //Trying to switch to it crashes to desktop
}
void ThisFunctionWillNotCrash()
{
Debug.Log("ThisFunctionWillNotCrash()");
var track = _mediaPlayer.Media.TrackList(TrackType.Audio)[0]; //Select the first audio track from MediaPlayer.Media
if (IsAudioTrackPlayable(track)) //This figures out that switching to this track won't work
_mediaPlayer.Select(track);
else
Debug.LogError("Cannot switch to track: " + track.Name); //Log an error instead of crashing
}
bool IsAudioTrackPlayable(MediaTrack track)
{
var tracks = _mediaPlayer.Tracks(TrackType.Audio);
foreach (var audiotrack in tracks)
if (audiotrack == track)
return true;
return false;
}
#endregion
What is the current bug behavior?
Unity crashes to desktop if you try to switch to a track VLC isn't prepared for. In this example, I get the track from MediaPlayer.Media.Tracklist instead of MediaPlayer.Tracks.
What is the expected correct behavior?
Perhaps in this specific example, because the track belongs to the video being played, it should probably just play the track. But there's probably a reason why it can't, and that would be no big deal.
In general, if you call MediaPlayer.Select on a track that it cannot or doesn't want to play, it would be a big improvement to throw some kind of "bad track exception" or just log a console message saying it couldn't select that track, rather than crashing to desktop.
Does it work on other plaforms? Does it work with the official VLC apps?
Right now VLC for Unity only supports one platform. I have never noticed VLC crashing when switching tracks.
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 version 0.1.3
- Scripting backend used Mono
Possible fixes
Checking if MediaPlayer.Tracks contains the track to be selected, before you call MediaPlayer.Select, seems to fix it.
Because of how easy it is to trigger the bug (you can get bad tracks from MediaPlayer.Media, or from a different MediaPlayer, or from an old video that you played earlier, probably a bunch of other ways) and how serious the consquences are (crash to desktop), I think this check should be part of MediaPlayer.Select, rather than leaving it up to the user to implement themselves (after figuring out the hard way by crashing Unity, probably.)