0

I'm trying to use LibVLCSharp with a playlist ( or that's the plan) and am testing it out with a basic loop between two different videos. I'm using this in WPF. The UI has a button to start the first video playing. If I don't loop and click the button each time, the next video will play as expected. Let it loop and threading error occurs on second video. I have checked out some of the other posts here on SO - How to achieve looping playback with Libvlcsharp and the various links within there, but I'm missing something. I'm hoping someone has a suggestion - or two! Thanks.

XAML
<Window
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:wpf="clr-namespace:LibVLCSharp.WPF;assembly=LibVLCSharp.WPF"
        xmlns:local="clr-namespace:testVLC"
        xmlns:Properties="clr-namespace:testVLC.Properties" x:Class="testVLC.MainWindow"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width=".2*"/>
            <ColumnDefinition Width="1*"/>
            <ColumnDefinition Width="1*"/>
            <ColumnDefinition Width="1*"/>
            <ColumnDefinition Width="1*"/>
            <ColumnDefinition Width=".2*"/>
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
            <RowDefinition Height=".25*"/>
            <RowDefinition Height="2*"/>
            <RowDefinition Height="1*"/>
            <RowDefinition Height=".25*"/>
            <RowDefinition Height=".25*"/>
        </Grid.RowDefinitions>
        <wpf:VideoView x:Name="VLC_player" Grid.Column="1" Grid.ColumnSpan="4" Grid.Row="0" Grid.RowSpan="3" Background="Black" Loaded="VLC_player_Loaded"/>
        <Button x:Name="go_Btn" Content="Press to view video" Grid.Column="2" HorizontalAlignment="Right"  Grid.Row="3" Padding="4,1" Margin="0,0,1,0" Click="Button_click"/>
        <TextBox x:Name="countTBox" Grid.Column="2" HorizontalAlignment="Left"  Grid.Row="3" Width="30" VerticalContentAlignment="Stretch"/>


    </Grid>
</Window>


CS

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using LibVLCSharp.Shared;
using MediaPlayer = LibVLCSharp.Shared.MediaPlayer;

namespace testVLC
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        LibVLC _libVLC;
        MediaPlayer media_player;
        bool init_flag = false;
        bool Web_flag = false;
        int count = 0;

        public MainWindow()
        {
            InitializeComponent();
        }


        private async void Media_play (string URI)
        {
            if (init_flag)
            {
                if(Web_flag)
                {
                    _libVLC = new LibVLC("--verbose=2");
                    Media media = new Media(_libVLC, (URI), FromType.FromLocation);
                    await media.Parse(MediaParseOptions.ParseNetwork);

                    media_player = new MediaPlayer(media.SubItems.First());
                    VLC_player.MediaPlayer = media_player;
                    media_player.EndReached += Video_Ended;
                    media_player.Play();
                    //MessageBox.Show(Thread.CurrentThread.Name);
                }
                else
                {
                    _libVLC = new LibVLC();
                    media_player = new MediaPlayer(_libVLC);

                    VLC_player.MediaPlayer = media_player;
                    media_player.EndReached += Video_Ended;
                    media_player.Play(new Media(_libVLC, URI));

                }
            }

        }

        private  void Button_click(object sender, RoutedEventArgs e)
        {
            count++;
            this.Dispatcher.Invoke((Action)(() =>
            {
               countTBox.Text = count.ToString();
            }));
            Main_List();
        }

        private async void Video_Ended(object sender, EventArgs e)
        {
            //ThreadPool.QueueUserWorkItem(_ => media_player.Stop());//doesn't work
            await Task.Run(() => media_player.Stop());
            Web_flag = false;
            //Button_click(this, null);//Works fine when commented out and the "Press to view video" button is clicked each time. Not so much when looping.
        }

        private void Main_List()
        {
            if (count%2 == 0)//even
            {
                Media_play("C:\\Users\\echo_\\Downloads\\videoplayback (1).mp4");             
            }
            else//odd
            {
                Web_flag = true;    
                Media_play("https://youtu.be/UK4t59mhIhs");
            }
        }

        private void VLC_player_Loaded(object sender, RoutedEventArgs e)
        {
            init_flag = true;
            Core.Initialize();
        }

    }
}
Chris H.
  • 3
  • 4

1 Answers1

1

Don't try to call Stop at the VideoEnded event, I think there is a known issue in this area in libvlc 3 that hangs the program. Call .Play with the new media instead.

Also, I wouldn't recommend to use two different libvlc instances if you can avoid it. 1 LibVlc, and 1 Media Player, but multiple Play() on the same MediaPlayer would be the norm. You can pass different options as media options if you need to have different options (though some options are not available at the media level, like the verbosity option (in which case, I'd register a log callback and filter there))

cube45
  • 3,429
  • 2
  • 24
  • 35
  • 1
    Thanks. I took what you said and massaged it a bit. I used a timer event instead of the videoended event and things worked fine. I will get time (length of video) from the file and set up timer that way in my working program. – Chris H. Apr 20 '21 at 15:55