3

Does anyone know if the VLC project has a defined state machine for the libvlc_state_t states? The state machine states are exposed via libvlc and then again via bindings into other languages (for example, LibVLCSharp). The enum is documented here, but I can't find a description of transitions or other details.

Update

I'd like to see this get rolled into VLC docs at some point. While the state machine might seem obvious, I am encountering small oddities like the Buffering event getting called but the Media not seeming to pass through the Buffering state - it's still in the Playing state.

These little things add up and it would probably help improve developer experience to get them added. What I'm looking for as a solution is a typical state machine that includes at a minimum the states, the transitions, and notes about which events are actually fired on which transitions (and if they happen before or after the state actually changes). Anything around threading concerns (e.g. sync vs. async transitions) and allowable actions while in a given state are a bonus.

halfer
  • 19,824
  • 17
  • 99
  • 186
J Trana
  • 2,150
  • 2
  • 20
  • 32
  • Can you help me see how to solve this? https://stackoverflow.com/questions/69210874/libvlcsharp-will-get-stuck-playing-specific-videos-on-any-platform – bbhxwl Sep 16 '21 at 15:58

2 Answers2

2

I did some work to capture the observed behavior. This is incomplete and imperfect, but perhaps it may help others as they build on top of libvlc/LibVLCSharp (I was on v3.5.1, VideoLAN.LibVLC.Windows v3.0.14). The dashed arrows pointing to the right are to show when certain events fire. Note that some of these behaviors are potentially specific to the type of media or the fact that reading is occurring through the MediaInput interface, so your mileage may vary.

State Machine

A few notes:

  • Things did not seem to always work properly if you tried to e.g. seek while the media was Opening. For example, I saw .Time and .Position fall permanently out of sync. I strongly recommend waiting until after a Play() operation before doing much.
  • The Buffering state was not seen to be in use, but the Buffering event would fire at least the Opening and Playing states.
  • As others have noted, you can't simply call Play() once the media ends. You need to Stop() after EndReached fires, and - as with many of the callbacks - you need to make sure you handle this in a non-deadlocking way. It can and will silently deadlock. Even using Dispatcher may choose to run on the same thread, so you have to guarantee a separate thread. So far I've had good luck with e.g. ThreadPool.QueueUserWorkItem(_ => yourMediaPlayer.Stop()); You can then hook Stopped to trigger further behavior like Play().
  • I'm still not sure the exact behavior around ErrorEncountered and recovery to Play() again; it wasn't easy to trigger this behavior.

Ultimately this state machine allowed me to build one on top of it to handle behaviors like "make the file playable again when the end is reached".

Thanks @mfkl and many others for the hard work - with a bit of digging this has been a great library to build on!

J Trana
  • 2,150
  • 2
  • 20
  • 32
  • 1
    Good job taking time to build this, hope it will be useful to others. – mfkl Jul 26 '21 at 01:30
  • Thanks! If you've got other input I can turn this into a community wiki too so everybody can get in on the action. – J Trana Jul 26 '21 at 17:26
0
media.State

Should give you what you want.

The libvlc_state_t C enum is simply defined as a C# enum in libvlcsharp, like so:

/// <summary>Note the order of libvlc_state_t enum must match exactly the order of</summary>
    /// <remarks>
    /// <para>mediacontrol_PlayerStatus,</para>
    /// <para>input_state_e enums,</para>
    /// <para>and VideoLAN.LibVLCSharp.State (at bindings/cil/src/media.cs).</para>
    /// <para>Expected states by web plugins are:</para>
    /// <para>IDLE/CLOSE=0, OPENING=1, PLAYING=3, PAUSED=4,</para>
    /// <para>STOPPING=5, ENDED=6, ERROR=7</para>
    /// </remarks>
    public enum VLCState
    {
        /// <summary>
        /// Nothing special happening
        /// </summary>
        NothingSpecial = 0,

        /// <summary>
        /// Opening media
        /// </summary>
        Opening = 1,

        /// <summary>
        /// Buffering media
        /// </summary>
        Buffering = 2,

        /// <summary>
        /// Playing media
        /// </summary>
        Playing = 3,

        /// <summary>
        /// Paused media
        /// </summary>
        Paused = 4,

        /// <summary>
        /// Stopped media
        /// </summary>
        Stopped = 5,

        /// <summary>
        /// Ended media
        /// </summary>
        Ended = 6,

        /// <summary>
        /// Error media
        /// </summary>
        Error = 7
    }

You can also subscribe to the StateChanged event on the Media to get notified of changes in the State status.

mfkl
  • 1,914
  • 1
  • 11
  • 21
  • Well, thank you - but this doesn't describe the state machine, only a brief description of the states. I don't know other critical details like what events cause transitions between the states. There's an example for a [processes and threads state machine over here](https://www.d.umn.edu/~gshute/os/processes-and-threads.html) that is closer to what I thought might exist in the docs someplace. This can help answer many practical types of questions like: "Would resetting media escape the Error state?" or "Can I do this action while the media is Paused or does it need to be Playing?". – J Trana Jul 14 '21 at 14:35
  • there is no such thing in the documentation. But it should be pretty straightforward to figure out (e.g. call Play() and Playing is the current state, after Opening and Buffering. etc) – mfkl Jul 15 '21 at 02:12
  • Right, but there are weird things. For example: if I set `MediaPlayer.Position` when I haven't done something around `MediaPlayer.Play()` and it has initialized, then `MediaPlayer.Position` and `MediaPlayer.Time` seem to fall permanently out of sync. State machines help ensure you avoid issues like this. – J Trana Jul 15 '21 at 16:10
  • Sure, but that's not documented :/ Some properties may be invalid if the media playback has not been started. – mfkl Jul 16 '21 at 06:46
  • it would be _a lot_ of work to describe a state machine of all possible states, considering all the various protocols / errors that may happen, and it'd be subject to change anyway, because event orders and object states are not part of the official/supported/backward-compatible API effort – mfkl Jul 16 '21 at 06:56
  • I don't disagree. But I'm hopeful that - even if it were a bit simplified, like "an error of some kind occurred in any state -> transition to Error state, with no exit transitions" - that it would still be helpful. Right now it just seems like without some of those details it would be difficult to create a bug-free media playback/timeline control. Maybe if I'm not hearing anything back after a while I'll post my early findings as it is probably better than nothing. – J Trana Jul 16 '21 at 12:26