From 474d7337ba3c4959115ce026c08f22ffaba657fa Mon Sep 17 00:00:00 2001 From: Martin Finkel Date: Mon, 26 Apr 2021 12:48:54 +0700 Subject: [PATCH] Media: Internally keep a reference to the last set Media libvlc_media_player_get_media increments the ref count of the media, which may easily cause a memory leak, as this is very unusual behavior for C# property getter to have these types of consequences. Users don't have the reflex to dispose every Media returned by the getter property. Holding a ref internally in the mediaplayer prevents from incrementing the native ref count of the media object. https://code.videolan.org/videolan/LibVLCSharp/-/issues/442 --- src/LibVLCSharp/Shared/MediaPlayer.cs | 28 +++++++++++++++++++-------- 1 file changed, 20 insertions(+), 8 deletions(-) diff --git a/src/LibVLCSharp/Shared/MediaPlayer.cs b/src/LibVLCSharp/Shared/MediaPlayer.cs index 81a2f052b..f04756ece 100644 --- a/src/LibVLCSharp/Shared/MediaPlayer.cs +++ b/src/LibVLCSharp/Shared/MediaPlayer.cs @@ -34,11 +34,6 @@ readonly struct Native internal static extern void LibVLCMediaPlayerSetMedia(IntPtr mediaPlayer, IntPtr media); - [DllImport(Constants.LibraryName, CallingConvention = CallingConvention.Cdecl, - EntryPoint = "libvlc_media_player_get_media")] - internal static extern IntPtr LibVLCMediaPlayerGetMedia(IntPtr mediaPlayer); - - [DllImport(Constants.LibraryName, CallingConvention = CallingConvention.Cdecl, EntryPoint = "libvlc_media_player_event_manager")] internal static extern IntPtr LibVLCMediaPlayerEventManager(IntPtr mediaPlayer); @@ -623,8 +618,11 @@ public MediaPlayer(Media media) : base(() => Native.LibVLCMediaPlayerNewFromMedia(media.NativeReference), Native.LibVLCMediaPlayerRelease) { _gcHandle = GCHandle.Alloc(this); + _media = media; } + Media? _media; + /// /// Get the media used by the media_player. /// Set the media that will be used by the media_player. @@ -635,10 +633,19 @@ public Media? Media { get { - var mediaPtr = Native.LibVLCMediaPlayerGetMedia(NativeReference); - return mediaPtr == IntPtr.Zero ? null : new Media(mediaPtr); + return _media; + } + set + { + if(_media?.NativeReference != IntPtr.Zero) + { + _media?.Dispose(); + _media = null; + } + + _media = value; + Native.LibVLCMediaPlayerSetMedia(NativeReference, value?.NativeReference ?? IntPtr.Zero); } - set => Native.LibVLCMediaPlayerSetMedia(NativeReference, value?.NativeReference ?? IntPtr.Zero); } /// @@ -2406,6 +2413,11 @@ protected override void Dispose(bool disposing) { if (_gcHandle.IsAllocated) _gcHandle.Free(); + if (_media?.NativeReference != IntPtr.Zero) + { + _media?.Dispose(); + _media = null; + } } base.Dispose(disposing);