【问题标题】:VLC libvlc_state_t State Machine?VLC libvlc_state_t 状态机?
【发布时间】:2021-09-22 19:33:34
【问题描述】:

有谁知道 VLC 项目是否为libvlc_state_t 状态定义了状态机?状态机状态通过 libvlc 公开,然后再次通过绑定到其他语言(例如,LibVLCSharp)。枚举记录在 here,但我找不到转换或其他详细信息的描述。

更新

我希望看到它在某个时候被纳入 VLC 文档。虽然状态机可能看起来很明显,但我遇到了一些小问题,例如调用了 Buffering 事件但 Media 似乎没有通过 Buffering 状态 - 它仍处于 Playing 状态。

这些小东西加起来可能有助于改善开发人员的体验来添加它们。我正在寻找的解决方案是一个典型的状态机,它至少包括状态、转换和关于哪些事件在哪些转换上实际触发的注释(以及它们是否发生在状态实际更改之前或之后)。任何与线程相关的问题(例如同步与异步转换)和在给定状态下允许的操作都是一个奖励。

【问题讨论】:

标签: libvlc fsm libvlcsharp


【解决方案1】:
media.State

应该给你你想要的。

libvlc_state_t C 枚举在 libvlcsharp 中被简单地定义为 C# 枚举,如下所示:

/// <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
    }

您还可以在媒体上订阅StateChanged 事件,以获取有关State 状态变化的通知。

【讨论】:

  • 嗯,谢谢 - 但这并没有描述状态机,只是对状态的简要描述。我不知道其他关键细节,例如哪些事件会导致状态之间的转换。 processes and threads state machine over here 有一个例子,它更接近我认为可能存在于文档中的某个地方。这可以帮助回答许多实际类型的问题,例如:“重置媒体会脱离错误状态吗?”或“我可以在媒体暂停或需要播放时执行此操作吗?”。
  • 文档中没有这样的东西。但这应该很容易弄清楚(例如,调用 Play() 并且 Playing 是当前状态,在打开和缓冲之后等)
  • 对,但是有些奇怪的事情。例如:如果我在MediaPlayer.Play() 周围没有做任何事情并且它已经初​​始化时设置MediaPlayer.Position,那么MediaPlayer.PositionMediaPlayer.Time 似乎永久不同步。状态机有助于确保您避免此类问题。
  • 当然可以,但没有记录:/如果媒体播放尚未开始,某些属性可能无效。
  • 考虑到所有可能发生的各种协议/错误,描述所有可能状态的状态机将是大量工作,并且它会受到无论如何都要改变,因为事件顺序和对象状态不是官方/支持/向后兼容 API 工作的一部分
【解决方案2】:

我做了一些工作来捕捉观察到的行为。这是不完整和不完美的,但也许它可以帮助其他人,因为他们建立在 libvlc/LibVLCSharp 之上(我在 v3.5.1,VideoLAN.LibVLC.Windows v3.0.14)。指向右侧的虚线箭头用于显示某些事件何时触发。请注意,其中一些行为可能特定于媒体类型或读取是通过MediaInput 接口发生的事实,因此您的里程可能会有所不同。

一些注意事项:

  • 如果您尝试例如,事情似乎并不总是正常工作。在媒体为Opening 时寻找。例如,我看到.Time.Position 永久不同步。我强烈建议等到Play() 操作之后再做很多事情。
  • 没有看到Buffering 状态正在使用,但Buffering 事件至少会触发OpeningPlaying 状态。
  • 正如其他人所指出的,一旦媒体结束,您不能简单地致电Play()。在EndReached 触发后,您需要Stop(),并且-与许多回调一样-您需要确保以非死锁方式处理此问题。它可以而且将会默默地陷入僵局。即使使用Dispatcher 可能会选择在同一个线程上运行,所以你必须保证一个单独的线程。到目前为止,我运气不错,例如ThreadPool.QueueUserWorkItem(_ =&gt; yourMediaPlayer.Stop()); 然后您可以挂钩 Stopped 以触发进一步的行为,例如 Play()
  • 我仍然不确定ErrorEncountered 周围的确切行为以及再次恢复到Play();触发这种行为并不容易。

最终,这个状态机允许我在它之上构建一个来处理诸如“使文件在到达结尾时再次可播放”之类的行为。

感谢 @mfkl 和其他许多人的辛勤工作 - 经过一番挖掘,这是一个很棒的库!

【讨论】:

  • 花时间构建这个做得很好,希望对其他人有用。
  • 谢谢!如果您有其他意见,我也可以将其变成社区 wiki,以便每个人都参与其中。
猜你喜欢
  • 1970-01-01
  • 2012-01-28
  • 1970-01-01
  • 2013-01-25
  • 1970-01-01
  • 2023-03-27
  • 1970-01-01
  • 2023-04-01
  • 1970-01-01
相关资源
最近更新 更多