Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

WPF MediaElement Video freezes

I am using Image and MediaElement in wpf project, where I show Images and Videos from file system. I have few timers, which load files to Image/MediaElement controls. Everything works for 4-5 hours, but then MediaElement Video file freezes and MediaEnded event does not occur. I restart the application, it runs without any problem, but after some hours this problem occurs again.

My WPF XAML code:

<Grid Name="MainGrid">
    <Image HorizontalAlignment="Center" VerticalAlignment="Center" Name="MainImage" Stretch="Fill" />
    <MediaElement MediaEnded="MediaEnded" MediaOpened="MediaOpened" LoadedBehavior="Manual" HorizontalAlignment="Center" Name="VideoControl" VerticalAlignment="Center"  
                   Stretch="Fill" UnloadedBehavior="Manual"/>
</Grid>

C# code:

public partial class ImageView
{
    private static readonly Logger Log = LogManager.GetCurrentClassLogger();
    private static String _advCheckGuid;
    private List<String> _FolderNames;
    private int _FolderIndex = 0;
    private MainWindow _MainWindow;
    private List<String> _PathList;
    private List<String> _CheckPathList; 
    private int _Index;
    private BitmapImage _BitmapImage;
    private volatile bool _Running = true;
    private Backend _Backend;
    private ApplicationDeployment _UpdateCheck;

    // Threads
    private Timer _ImageTimer;
    private Timer _UpdateTimer;
    private Timer _FolderClearTimer;
    private Timer _CheckApplicationUpdateTimer;
    private Thread _TerminationThread;


    public ImageView()
    {
        InitializeComponent();
        _PathList = new List<string>();
        _CheckPathList = new List<string>();
        _Index = 0;

    }

    private void ViewPageLoaded(Object sender, EventArgs e)
    {

        _FolderNames = new List<string> { Constants.AdsFolderFirst, 
                                          Constants.AdsFolderSecond };

        _Backend = new Backend();



        _MainWindow = (MainWindow)Window.GetWindow(this);


        _ImageTimer = new Timer(Constants.DefaultImageTimer);
        _ImageTimer.Elapsed += ChangeImageSource;
        _ImageTimer.Start();


    }


    private void ChangeImageSource(object sender, System.Timers.ElapsedEventArgs e)
    {
        Application.Current.Dispatcher.Invoke(
            DispatcherPriority.Normal, new Action(
                  delegate()
                  {
                      try
                      {
                          if (MainImage != null && MainImage.Source != null)
                          {
                              MainImage.Source = null;
                          }

                          if (VideoControl != null && VideoControl.Source != null)
                          {
                              VideoControl.Stop();
                              VideoControl.Source = null;
                          }

                          if (_Index >= _PathList.Count)
                          {
                              _Index = 0;
                          }

                          if (_PathList.ElementAt(_Index) != null)
                          {

                              Log.Info(String.Format("Start [ChangeImageSource]. Element: {0}, Index: {1}", _PathList.ElementAt(_Index), _Index));

                              try
                              {
                                  _ImageTimer.Stop();

                                  String[] checkExt = _PathList.ElementAt(_Index).Split('.');
                                  String ext = checkExt[checkExt.Length - 1];

                                  if (ext.Equals("jpg", StringComparison.CurrentCultureIgnoreCase) ||
                                      ext.Equals("jpeg", StringComparison.CurrentCultureIgnoreCase) ||
                                      ext.Equals("png", StringComparison.CurrentCultureIgnoreCase))
                                  {
                                      _ImageTimer.Interval = Constants.NormalImageTimer;
                                      ShowImage(_PathList.ElementAt(_Index));
                                  }

                                  else if (ext.Equals("mp4", StringComparison.CurrentCultureIgnoreCase) ||
                                           ext.Equals("3gp", StringComparison.CurrentCultureIgnoreCase))
                                  {
                                      _ImageTimer.Interval = Constants.VideoDefaultTimer;
                                      PlayQueue(_PathList.ElementAt(_Index));
                                  }

                                  _ImageTimer.Start();
                                  _Index++;
                              }
                              catch (Exception exception)
                              {
                                  Log.ErrorException(exception.Message, exception);
                              }
                          }
                      }
                      catch (Exception exception)
                      {
                          Log.ErrorException(exception.Message, exception);
                      }
                  }));
    }


    private void ShowImage(String fileName)
    {
        try
        {
            if (!String.IsNullOrEmpty(fileName))
            {

                _BitmapImage = LoadImage(fileName);
                MainImage.Source = _BitmapImage;

            }
        }
        catch (Exception e)
        {
            Log.ErrorException(e.Message, e);
        }
    }


    private void PlayQueue(String fileName)
    {

        try
        {
            if (!String.IsNullOrEmpty(fileName))
            {
                VideoControl.LoadedBehavior = MediaState.Play;
                VideoControl.Source = new Uri(fileName, UriKind.Absolute);
            }
        }
        catch (Exception e)
        {
            Log.ErrorException(e.Message, e);
        }

    }



    private void MediaEnded(object sender, EventArgs e)
    {
        try
        {
            if (MainImage != null && MainImage.Source != null)
            {
                MainImage.Source = null;
            }

            if (VideoControl != null && VideoControl.Source != null)
            {
                VideoControl.Stop();
                VideoControl.Source = null;
            }

            if (_Index >= _PathList.Count)
            {
                _Index = 0;
            }

            if (_PathList.ElementAt(_Index) != null)
            {

                Log.Info(String.Format("Start [MediaEnded oper]. Element: {0}, Index: {1}", _PathList.ElementAt(_Index), _Index));

                try
                {
                    _ImageTimer.Stop();

                    String[] checkExt = _PathList.ElementAt(_Index).Split('.');
                    String ext = checkExt[checkExt.Length - 1];

                    if (ext.Equals("jpg", StringComparison.CurrentCultureIgnoreCase) ||
                        ext.Equals("jpeg", StringComparison.CurrentCultureIgnoreCase) ||
                        ext.Equals("png", StringComparison.CurrentCultureIgnoreCase))
                    {
                        _ImageTimer.Interval = Constants.NormalImageTimer;
                        ShowImage(_PathList.ElementAt(_Index));
                    }

                    else if (ext.Equals("mp4", StringComparison.CurrentCultureIgnoreCase) ||
                             ext.Equals("3gp", StringComparison.CurrentCultureIgnoreCase))
                    {
                        _ImageTimer.Interval = Constants.VideoDefaultTimer;
                        PlayQueue(_PathList.ElementAt(_Index));
                    }

                    _ImageTimer.Start();
                    _Index++;
                }
                catch (Exception exception)
                {
                    Log.ErrorException(exception.Message, exception);
                }
            }
        }
        catch (Exception exception)
        {
            Log.ErrorException(exception.Message, exception);
        }

    }



    private void MediaOpened(object sender, EventArgs e)
    {

    }



    private BitmapImage LoadImage(string myImageFile)
    {
        BitmapImage myRetVal = null;

        if (!String.IsNullOrEmpty(myImageFile))
        {
            var image = new BitmapImage();
            try
            {
                using (FileStream stream = File.OpenRead(myImageFile))
                {
                    image.BeginInit();
                    image.CacheOption = BitmapCacheOption.OnLoad;
                    image.StreamSource = stream;
                    image.EndInit();
                }
            }
            catch (Exception exception)
            {
                Log.ErrorException(exception.Message, exception);
            }

            myRetVal = image;
        }

        return myRetVal;
    }
like image 817
0bj3ct Avatar asked Apr 15 '14 05:04

0bj3ct


1 Answers

I googled it and found that this was WPF graphic issue related to software rendering. The issue is solved by adding this piece of code into the ViewPageLoaded method.

        try
        {
            var hwndSource = PresentationSource.FromVisual(this) as HwndSource;
            var hwndTarget = hwndSource.CompositionTarget;
            hwndTarget.RenderMode = RenderMode.SoftwareOnly;
        }
        catch (Exception ex)
        {
            Log.ErrorException(ex.Message, ex);
        }

It helped me to solve the problem. Hope it will help you too.

Got the answer from here. Thanks to @detale for the solution

like image 137
0bj3ct Avatar answered Sep 18 '22 00:09

0bj3ct