1

After playing a playlist for about two days the memory increases from a about 100 megabytes to a few gigabytes. The thread count remains the same about 20 threads. I'm disposing of media (when changin to new media) from mediaplayer element like so:

                            if(web.MediaPlayer.Media != null) {
                                web.MediaPlayer.Media.Dispose();
                            }
                    
                            web.MediaPlayer.Media = media;

and when creatinga new media player:

                            if(web.MediaPlayer != null) {
                                if(web.MediaPlayer.Media != null) {
                                    web.MediaPlayer.Media.Dispose();
                                }
                                web.MediaPlayer.Dispose();
                            }

                            web.MediaPlayer = new MediaPlayer(media) { EnableHardwareDecoding = true };

Is this enough to dispose of the media like this?

And when reaching end i play next media like this, calling init video calls the first piece of code. Switching the media in the media player.

                    web.MediaPlayer.EndReached += (s, e) => ThreadPool.QueueUserWorkItem(_ => { 
                        if(this.tab_objects.ContainsKey(tab_index)) {
                            tab tab_object = this.tab_objects[tab_index];
                            string next_media = tab_object.get_next_media();
                            ....some other code....
                            if(next_media != null) {
                                this.init_video(next_media, tab_index, true);
                            } else {
                                
                    
                            }
                        }
                    });

Any help is appreciated.

I've altered the code to this with no results:

            using(Media media = new Media(this.lib_vlc, uri)) {
                using(MediaPlayer p = web.MediaPlayer) {
                    if(p != null) {
                        /*using(Media last_media = p.Media) {
                            if(last_media != null) {
                                last_media.Dispose();
                            }
                        }*/
                    }   
                    web.MediaPlayer = null;
                    if(p != null) {
                        p.Dispose();
                    }
                    web.MediaPlayer = new MediaPlayer(media) { EnableHardwareDecoding = true };
                    media.Dispose();
                }
            }

I've commented out the "last_media" part because it has no effect. I set the web.MediaPlayer as null because it causes a crash when i dispose of the MediaPlayer object before setting it to something else.

I would wrapping the media in "using" and explicitly disposing of it would be enough. But the memory usage still climbs. What is the correct way of disposing of the last played media object?

1 Answers1

1

Calling MediaPlayer.Media calls the native function that gets the media, and creates a new instance of Media. Every time you're calling the property, you'll get a new instance. This is not really a problem from the C# side, because all these instance will be garbage collected, but they are not Disposed of properly. The native get media function internally increments a reference counter, that is decremented when you call Dispose.

If you're calling N times MediaPlayer.Media, you're incrementing N times the ref counter, but releasing it only once when you call Dispose.

Another related note : when you pass a media to the media player, you can (and probably should if you're not reusing it) Dispose it immediately (i.e. decrement the reference count and let libvlc be the only reference usage)

EDIT : To clarify, instead of doing your operations on MediaPlayer.Media, you should store the result of the property and Dispose it when you're done with it

cube45
  • 3,429
  • 2
  • 24
  • 35
  • I call dispose exactly once after assigning MediaPlayer.Media once each time. And i am now disposing of the media element immediately after assigning MediaPlayer.Media, but still the memory is increasing. I'm not sure what you mean by "every time you call the property" do you mean when i assign the property? – Sigurður Jökull Feb 20 '21 at 17:42
  • when you call the getter, you are getting a new instance every time – cube45 Feb 20 '21 at 18:23
  • doesn't that mean even when calling MediaPlayer.Media.Dispose() i'm getting a new instance, so it has no effect at all? – Sigurður Jökull Feb 20 '21 at 18:55
  • I think i understand now what i was doing wrong, i've changed all the calls to the getters of MediaPlayer and Media objects to using statements where i define a variable from the gotten property. However i keep getting: Got a segv while executing native code. when trying to play the video after setting the MediaPlayer element with the Media, like the MediaPlayer object is getting disposed of somehow right away (or atleast seems like that) Does the getter for MediaPlayer not create a new instance each time like Media? – Sigurður Jökull Feb 20 '21 at 20:15
  • The MediaPlayer property on the VideoView object is a C# only feature and isn't a native call. As opposed to MediaPlayer.Media, VideoView.MediaPlayer returns the same instance every time and does not create new instances. You only need to Dispose of the MediaPlayer when you're done playing videos – cube45 Feb 20 '21 at 21:07
  • Ok, thanks for all the help so far, but i'm still not getting this right, can you please view my edit to my question. Just to be clear i changed the code from changing the Media object of a MediaPlayer object to just changing the MediaPlayer object and trying to dispose of the Media and the MediaPlayer object. – Sigurður Jökull Feb 20 '21 at 21:18
  • Use one media player that has the same lifetime as your window and your view : Dispose it when your view is destroyed. – cube45 Feb 21 '21 at 07:10
  • In that MediaPlayer, set as many Media that you want. Just after you've called `.Media =`, you can Dispose the Media. – cube45 Feb 21 '21 at 07:11
  • The memory usage still grows, very slowly but surely. It might be becuase i'm using multiple MediaPlayers, when i remove a VideoView view element from my view isn't it enough to call paret_element.Remove(video_view_element) (removing it fromt he view), then to call video_view_element.MediaPlayer.Dispose(); ? And i'm setting the .Media property inside a using statement and disposing the Media right after setting it. Should that be enough? – Sigurður Jökull Feb 22 '21 at 09:49
  • To clarify i'm now only using one MediaPlayer per VideoView and just changing the media, but my app has multiple VideoViews and each VideoView has one MediaPlayer – Sigurður Jökull Feb 22 '21 at 09:51
  • The memory increments each time the MediaPlayer switches Media, the memory increases by larger increments when switching to next media when in fullscreen (the applications is running on macOS). I've tried doing everything you've suggested. Now i'm never calling the getter of MediaPlayer.Media, i previously tried storing the result of the getter and then disposing of it when switching to new Media but it seemed to have no effect. So i'm never calling the getter simply setting the Media, and disposing of the Media object, after setting the property like you suggested. – Sigurður Jökull Feb 22 '21 at 15:50
  • Please open an issue with a sample code hosted on github so that we can have a look. You could also try to diagnose the issue with a memory profiler – cube45 Feb 22 '21 at 19:10
  • Issues are disabled on the github repository, can you direct me to the correct place to post an issue? Here is a repository demonstrating the issue: https://github.com/siggi90/video_test/blob/main/video_test/MainPage.xaml.cs you must add files to the playlist List then launch the application and see that memory grows over time. – Sigurður Jökull Feb 23 '21 at 13:49
  • https://code.videolan.org/videolan/libvlcsharp is the place to go – cube45 Feb 23 '21 at 17:05