La vidéo de WPF MediaElement se fige

J’utilise Image et MediaElement dans le projet wpf, où je montre des images et des vidéos du système de fichiers. J’ai peu de timers, qui chargent les fichiers dans les contrôles Image / MediaElement. Tout fonctionne pendant 4 à 5 heures, mais le fichier vidéo MediaElement se fige alors et l’événement MediaEnded ne se produit pas. Je redémarre l’application, elle fonctionne sans aucun problème, mais après quelques heures, ce problème se reproduit.

Mon code WPAM XAML:

    

Code C #:

 public partial class ImageView { private static readonly Logger Log = LogManager.GetCurrentClassLogger(); private static Ssortingng _advCheckGuid; private List _FolderNames; private int _FolderIndex = 0; private MainWindow _MainWindow; private List _PathList; private List _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(); _CheckPathList = new List(); _Index = 0; } private void ViewPageLoaded(Object sender, EventArgs e) { _FolderNames = new List { 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(Ssortingng.Format("Start [ChangeImageSource]. Element: {0}, Index: {1}", _PathList.ElementAt(_Index), _Index)); try { _ImageTimer.Stop(); Ssortingng[] checkExt = _PathList.ElementAt(_Index).Split('.'); Ssortingng ext = checkExt[checkExt.Length - 1]; if (ext.Equals("jpg", SsortingngComparison.CurrentCultureIgnoreCase) || ext.Equals("jpeg", SsortingngComparison.CurrentCultureIgnoreCase) || ext.Equals("png", SsortingngComparison.CurrentCultureIgnoreCase)) { _ImageTimer.Interval = Constants.NormalImageTimer; ShowImage(_PathList.ElementAt(_Index)); } else if (ext.Equals("mp4", SsortingngComparison.CurrentCultureIgnoreCase) || ext.Equals("3gp", SsortingngComparison.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(Ssortingng fileName) { try { if (!Ssortingng.IsNullOrEmpty(fileName)) { _BitmapImage = LoadImage(fileName); MainImage.Source = _BitmapImage; } } catch (Exception e) { Log.ErrorException(e.Message, e); } } private void PlayQueue(Ssortingng fileName) { try { if (!Ssortingng.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(Ssortingng.Format("Start [MediaEnded oper]. Element: {0}, Index: {1}", _PathList.ElementAt(_Index), _Index)); try { _ImageTimer.Stop(); Ssortingng[] checkExt = _PathList.ElementAt(_Index).Split('.'); Ssortingng ext = checkExt[checkExt.Length - 1]; if (ext.Equals("jpg", SsortingngComparison.CurrentCultureIgnoreCase) || ext.Equals("jpeg", SsortingngComparison.CurrentCultureIgnoreCase) || ext.Equals("png", SsortingngComparison.CurrentCultureIgnoreCase)) { _ImageTimer.Interval = Constants.NormalImageTimer; ShowImage(_PathList.ElementAt(_Index)); } else if (ext.Equals("mp4", SsortingngComparison.CurrentCultureIgnoreCase) || ext.Equals("3gp", SsortingngComparison.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(ssortingng myImageFile) { BitmapImage myRetVal = null; if (!Ssortingng.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; } 

C’est un problème compliqué. Je vais essayer de l’expliquer en profondeur. (et oui j’ai une solution pour vous)

Commençons par ce que MediaElement devrait être capable de faire? pas vraiment!

C’est un joker à droite? ce qui signifie que tout ce que vous y jetez – doit être joué: vidéos, images, Gifs animés, musique .. Ok ..
Maintenant .. Chacune de ces catégories a plusieurs formats (ou standards) .. Gif, Png .. Wmv, Mp4 …
Et ainsi, chacun de ces fichiers que nous utilisons a été créé par un autre éditeur
(qui a un lecteur qui peut le jouer implémenté à l’intérieur – c’est à coup sûr ..)

Il semble que la plupart des entresockets réduisent leurs dépenses – elles ne les implémentent pas toujours (généralement, c’est-à-dire ..) une norme complète.

Donc, quel est le format de fichier parfait pour un joueur peut être considéré comme trop corrompu pour un autre joueur.

Et tandis que les lecteurs commerciaux / avancés sont conçus pour être tolérants aux corruptions et aux «saveurs» d’un fichier écrit en standard – MediaElement – eh bien, c’est plus simpliste et peut-être trop simpliste par rapport à ce que vous pouvez lui lancer. .

Donc, quand il s’agit de ce type de problème – oui .. il peut geler et ne pas signaler – et c’est quelque chose que je peux reprocher à Microsoft en entier – et pourquoi? car il s’agit d’un défaut acceptable à geler mais il n’est pas acceptable (et extrêmement irresponsable!) de l’ignorer et de ne pas notifier au programme utilisant le MediaElement qu’il a gelé ou rencontré une erreur de présentation grave.
Mais comme je l’ai dit, il s’agit d’un problème Microsoft et certainement pas de votre faute.

Alors, quelles sont les solutions?

Vous pouvez essayer de vous dire “Bien – je vais juste avoir un autre composant pour lire des vidéos ou utiliser un plug-in tiers”, mais non mon ami, Faire cela ne résoudra pas vraiment votre problème car vous ne le savez pas si ce que vous êtes sur le sharepoint remplacer ne souffrirait pas du même problème.

Donc, la seule option qui vous rest est de créer votre propre standard “personnalisé” – relax, je ne veux pas dire que vous devez développer un nouveau standard – je veux juste dire que vous devez créer une tactique standard pour vous assurer que ce que vous allez jeter sur le MediaElement sera joué sans geler ..

Donc, si votre application va lire des vidéos utilisées en tant que ressources, vous pouvez utiliser la dernière version d’AnyVideoConverter pour convertir toutes vos vidéos en mp4. Pour moi, cela a plutôt bien fonctionné, les vidéos qui gèlaient dans wmv converties en mp4 et sont maintenant tolérées par le MediaElement très facilement. ce n’est pas le MP4 qui a fait l’affaire, mais la conversion elle-même – je crois que ANV crée un fichier vidéo “modernisé” de tous les standards que vous pouvez utiliser pour vos fichiers.

Cependant, si vos vidéos sont dynamics / téléchargées sur votre application pendant l’exécution ou quelque chose du genre – vous devrez vous assurer de transmettre toutes les vidéos que votre application est sur le sharepoint lire. MediaElement.

Par ailleurs, les navigateurs souffrent parfois du même problème.

J’espère juste que tout cela peut régler le problème pour quiconque l’a rencontré.

Vous créez beaucoup d’instances BitmapImage, il y a une fuite de mémoire dans la classe BitmapImage, BitmapImage conserve une référence au stream source (probablement pour que vous puissiez lire la propriété StreamSource à tout moment), afin de garder l’object MemoryStream en vie. Cela provoque une exception de sortie de mémoire. Lisez ceci , il a créé un joli wrapper pour stream, ça a fonctionné pour moi.

Il a créé une instance de stream dans la classe wrapper qui est supprimée lorsque vous appelez la méthode de wrapping et BitmapImage.Source ne dispose que d’une classe de wrapper vide qui n’a aucune référence au stream d’origine.

Je l’ai googlé et ai trouvé que c’était le problème graphique de WPF lié au rendu de logiciel. Le problème est résolu en ajoutant ce morceau de code dans la méthode ViewPageLoaded .

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

Cela m’a aidé à résoudre le problème. J’espère que cela vous aidera aussi.

J’ai la réponse d’ ici . Merci à @detale pour la solution

Je suggère de vous inscrire à l’événement MediaElement.MediaFailed . Voyez si cela vous retourne quelque chose.

Cependant, comme d’autres l’ont mentionné, cela ressemble à un problème de mémoire. Vous pouvez utiliser WPF Performance Suite ou même simplement le gestionnaire de tâches pour le confirmer. Surveillez l’augmentation très progressive de l’utilisation de la mémoire.

Comme Shivam cv l’a mentionné, il se pourrait que BitmapImage soit la fuite. Essayez de le commenter de votre solution et voyez si cela résout le problème.