[longomatch] Fix memory leak with unmanaged Pixbuf



commit d9cd83954fc38cf378c46ba56ea4fcbcf32c83a8
Author: Andoni Morales Alastruey <ylatuya gmail com>
Date:   Sun Sep 13 22:01:46 2009 +0200

    Fix memory leak with unmanaged Pixbuf

 CesarPlayer/Gui/PlayerBin.cs                     |   12 ++-----
 CesarPlayer/Player/GstPlayer.cs                  |   35 +++++++++++++++++----
 CesarPlayer/Player/IPlayer.cs                    |   10 +++---
 CesarPlayer/Utils/FramesCapturer.cs              |   18 +++++++++--
 CesarPlayer/Utils/IFramesCapturer.cs             |    6 ++--
 CesarPlayer/Utils/PreviewMediaFile.cs            |   18 +++++------
 LongoMatch/Gui/FramesCaptureProgressDialog.cs    |   14 ++------
 LongoMatch/Handlers/EventsManager.cs             |    2 +-
 LongoMatch/Time/PixbufTimeNode.cs                |    4 ++-
 libcesarplayer/src/bacon-video-widget-gst-0.10.c |    5 +++
 libcesarplayer/src/bacon-video-widget.h          |    1 +
 11 files changed, 76 insertions(+), 49 deletions(-)
---
diff --git a/CesarPlayer/Gui/PlayerBin.cs b/CesarPlayer/Gui/PlayerBin.cs
index b3e74ba..8eddc12 100644
--- a/CesarPlayer/Gui/PlayerBin.cs
+++ b/CesarPlayer/Gui/PlayerBin.cs
@@ -108,15 +108,9 @@ namespace LongoMatch.Gui
 		
 		public Pixbuf CurrentFrame{
 			get{
-				int h,w;
-				double rate;
-				Pixbuf pixbuf = player.CurrentFrame;
-				if (pixbuf != null){
-					h = pixbuf.Height;
-					w = pixbuf.Width;
-					rate = (double)w/(double)h;
-					return pixbuf.ScaleSimple(THUMBNAIL_WIDTH,(int)(THUMBNAIL_WIDTH/rate),InterpType.Bilinear);
-				}
+				Pixbuf pixbuf = player.GetCurrentFrame(50,50);				
+				if (pixbuf != null)
+					return pixbuf;
 				else return null;
 			}
 		}
diff --git a/CesarPlayer/Player/GstPlayer.cs b/CesarPlayer/Player/GstPlayer.cs
index 2c3444b..18e320e 100644
--- a/CesarPlayer/Player/GstPlayer.cs
+++ b/CesarPlayer/Player/GstPlayer.cs
@@ -1099,13 +1099,34 @@ namespace LongoMatch.Video.Player {
 
 		[DllImport("libcesarplayer.dll")]
 		static extern IntPtr bacon_video_widget_get_current_frame(IntPtr raw);
-
-		public Gdk.Pixbuf CurrentFrame { 
-			get {
-				IntPtr raw_ret = bacon_video_widget_get_current_frame(Handle);
-				Gdk.Pixbuf ret = GLib.Object.GetObject(raw_ret) as Gdk.Pixbuf;
-				return ret;
-			}
+		
+		[DllImport("libcesarplayer.dll")]
+		static extern IntPtr bacon_video_widget_unref_pixbuf(IntPtr raw);
+
+
+		public Gdk.Pixbuf GetCurrentFrame(int outwidth, int outheight) { 
+			IntPtr raw_ret = bacon_video_widget_get_current_frame(Handle);
+			Gdk.Pixbuf unmanaged = GLib.Object.GetObject(raw_ret) as Gdk.Pixbuf;
+			Gdk.Pixbuf managed;
+			int h = unmanaged.Height;
+			int w = unmanaged.Width;
+			double rate = (double)w/(double)h;
+			if (outwidth == -1 || outheight == -1){
+				outwidth = w;
+				outheight = h;
+			}else if (h>w){
+				outwidth = (int)(outheight*rate);
+			}else{
+				outheight = (int)(outwidth/rate);
+			}
+			managed = unmanaged.ScaleSimple(outwidth,outheight,Gdk.InterpType.Bilinear);
+			unmanaged.Dispose();
+			bacon_video_widget_unref_pixbuf(raw_ret);
+			return managed;
+		}
+		
+		public Gdk.Pixbuf GetCurrentFrame() { 
+			return GetCurrentFrame(-1,-1);
 		}
 
 		[DllImport("libcesarplayer.dll")]
diff --git a/CesarPlayer/Player/IPlayer.cs b/CesarPlayer/Player/IPlayer.cs
index a989b8b..f25f349 100644
--- a/CesarPlayer/Player/IPlayer.cs
+++ b/CesarPlayer/Player/IPlayer.cs
@@ -73,11 +73,7 @@ namespace LongoMatch.Video.Player
 		bool Playing {
 			get;
 		}
-		
-		Pixbuf CurrentFrame{
-			get;
-		}
-		
+			
 		string Logo {
 			set;
 		}
@@ -123,6 +119,10 @@ namespace LongoMatch.Video.Player
 		
 		bool SeekToPreviousFrame(float rate,bool in_segment);
 		
+		Pixbuf GetCurrentFrame(int outwidth, int outheight);
+		
+		Pixbuf GetCurrentFrame();
+		
 		void CancelProgramedStop();
 		
 	}
diff --git a/CesarPlayer/Utils/FramesCapturer.cs b/CesarPlayer/Utils/FramesCapturer.cs
index 6a3437a..0a9e30c 100644
--- a/CesarPlayer/Utils/FramesCapturer.cs
+++ b/CesarPlayer/Utils/FramesCapturer.cs
@@ -40,6 +40,8 @@ namespace LongoMatch.Video.Utils
 		string seriesName;
 		string outputDir;
 		bool cancel;
+		private const int THUMBNAIL_MAX_HEIGHT=250;
+		private const int THUMBNAIL_MAX_WIDTH=300;
 		
 		public event FramesProgressHandler Progress;
 		
@@ -68,6 +70,7 @@ namespace LongoMatch.Video.Utils
 		public void CaptureFrames(){		
 			long pos;
 			Pixbuf frame;
+			Pixbuf scaledFrame=null;
 			int i = 0;			
 						
 			System.IO.Directory.CreateDirectory(outputDir);	
@@ -79,12 +82,21 @@ namespace LongoMatch.Video.Utils
 				if (!cancel){					
 					capturer.SeekTime(pos,true);	
 					capturer.Pause();
-					frame = capturer.CurrentFrame;				
+					frame = capturer.GetCurrentFrame();				
 					if (frame != null) {
 						frame.Save(System.IO.Path.Combine(outputDir,seriesName+"_" + i +".png"),"png");
-					}			
+						int h = frame.Height;
+						int w = frame.Width;
+						double rate = (double)w/(double)h;
+						if (h>w)
+							scaledFrame = frame.ScaleSimple((int)(THUMBNAIL_MAX_HEIGHT*rate),THUMBNAIL_MAX_HEIGHT,InterpType.Bilinear);
+						else
+							scaledFrame = frame.ScaleSimple(THUMBNAIL_MAX_WIDTH,(int)(THUMBNAIL_MAX_WIDTH/rate),InterpType.Bilinear);
+						frame.Dispose();				
+					}
+					
 					if (Progress != null)					
-						Application.Invoke(delegate {Progress(i+1,totalFrames,frame);});
+						Application.Invoke(delegate {Progress(i+1,totalFrames,scaledFrame);});
 					pos += interval;
 					i++;
 				}
diff --git a/CesarPlayer/Utils/IFramesCapturer.cs b/CesarPlayer/Utils/IFramesCapturer.cs
index 545da0b..fec5eaf 100644
--- a/CesarPlayer/Utils/IFramesCapturer.cs
+++ b/CesarPlayer/Utils/IFramesCapturer.cs
@@ -31,8 +31,8 @@ namespace LongoMatch.Video.Utils
 		bool SeekTime(long time, bool accurate);
 		void Pause();
 		void Dispose();
-		Pixbuf CurrentFrame{
-			get;
-		}
+		Pixbuf GetCurrentFrame(int outwidth, int outheight);
+		Pixbuf GetCurrentFrame();
+		
 	}
 }
diff --git a/CesarPlayer/Utils/PreviewMediaFile.cs b/CesarPlayer/Utils/PreviewMediaFile.cs
index 021b5ea..754aa23 100644
--- a/CesarPlayer/Utils/PreviewMediaFile.cs
+++ b/CesarPlayer/Utils/PreviewMediaFile.cs
@@ -58,15 +58,9 @@ namespace LongoMatch.Video.Utils
 			}
 			set{
 				if (value != null){
-					int h = value.Height;
-					int w = value.Width;
-					double ratio = (double)w/(double)h;
-					if (h>w)
-						thumbnailBuf = value.ScaleSimple((int)(THUMBNAIL_MAX_HEIGHT*ratio),THUMBNAIL_MAX_HEIGHT,InterpType.Bilinear).SaveToBuffer("png");
-					else
-						thumbnailBuf = value.ScaleSimple(THUMBNAIL_MAX_WIDTH,(int)(THUMBNAIL_MAX_WIDTH/ratio),InterpType.Bilinear).SaveToBuffer("png");
+					thumbnailBuf = value.SaveToBuffer("png");
+					value.Dispose();
 				}
-								
 				else thumbnailBuf = null;
 			}
 		}
@@ -101,7 +95,7 @@ namespace LongoMatch.Video.Utils
 					thumbnailer = factory.getFramesCapturer();
 					thumbnailer.Open(filePath);
 					thumbnailer.SeekTime(1000,false);
-					preview = thumbnailer.CurrentFrame;
+					preview = thumbnailer.GetCurrentFrame(THUMBNAIL_MAX_WIDTH,THUMBNAIL_MAX_HEIGHT);
 					thumbnailer.Dispose();
 				}			
 				height = (int) reader.GetMetadata(GstMetadataType.DimensionY);
@@ -109,7 +103,11 @@ namespace LongoMatch.Video.Utils
 				reader.Close();	
 				reader.Dispose();	
 				
-				return new PreviewMediaFile(filePath,duration*1000,(ushort)fps,hasAudio,hasVideo,videoCodec,audioCodec,(uint)height,(uint)width,preview);
+				return new PreviewMediaFile(filePath,duration*1000,
+				                            (ushort)fps,hasAudio,
+				                            hasVideo,videoCodec,
+				                            audioCodec,(uint)height,
+				                            (uint)width,preview);
 			}
 			catch (GLib.GException ex){
 			    throw new Exception (Catalog.GetString("Invalid video file:")+"\n"+ex.Message);
diff --git a/LongoMatch/Gui/FramesCaptureProgressDialog.cs b/LongoMatch/Gui/FramesCaptureProgressDialog.cs
index d4be61f..aec1fba 100644
--- a/LongoMatch/Gui/FramesCaptureProgressDialog.cs
+++ b/LongoMatch/Gui/FramesCaptureProgressDialog.cs
@@ -32,9 +32,7 @@ namespace LongoMatch.Gui.Dialog
 	[System.ComponentModel.ToolboxItem(false)]
 	public partial class FramesCaptureProgressDialog : Gtk.Dialog
 	{
-		private FramesSeriesCapturer capturer;
-		private const int THUMBNAIL_MAX_HEIGHT=250;
-		private const int THUMBNAIL_MAX_WIDTH=300;
+		private FramesSeriesCapturer capturer;		
 		
 		public FramesCaptureProgressDialog(FramesSeriesCapturer capturer)
 		{
@@ -50,13 +48,9 @@ namespace LongoMatch.Gui.Dialog
 				progressbar.Text= Catalog.GetString("Capturing frame: ")+actual+"/"+total;
 				progressbar.Fraction = (double)actual/(double)total;
 				if (frame != null){
-					int h = frame.Height;
-					int w = frame.Width;
-					double rate = (double)w/(double)h;
-					if (h>w)
-						image.Pixbuf = frame.ScaleSimple((int)(THUMBNAIL_MAX_HEIGHT*rate),THUMBNAIL_MAX_HEIGHT,InterpType.Bilinear);
-					else
-						image.Pixbuf = frame.ScaleSimple(THUMBNAIL_MAX_WIDTH,(int)(THUMBNAIL_MAX_WIDTH/rate),InterpType.Bilinear);
+					if (image.Pixbuf != null)
+						image.Pixbuf.Dispose();
+					image.Pixbuf = frame;
 				}
 			}
 			if (actual == total){
diff --git a/LongoMatch/Handlers/EventsManager.cs b/LongoMatch/Handlers/EventsManager.cs
index bc977b1..b9b3d3c 100644
--- a/LongoMatch/Handlers/EventsManager.cs
+++ b/LongoMatch/Handlers/EventsManager.cs
@@ -134,7 +134,7 @@ namespace LongoMatch
 								
 				Time fStop = (stop > length) ? length: stop;
 				Pixbuf miniature = player.CurrentFrame;
-				MediaTimeNode tn = openedProject.AddTimeNode(section,fStart, fStop,miniature);				
+				MediaTimeNode tn = openedProject.AddTimeNode(section,fStart, fStop,miniature);	
 				treewidget.AddTimeNode(tn,section);
 				timeline.QueueDraw();
 			}
diff --git a/LongoMatch/Time/PixbufTimeNode.cs b/LongoMatch/Time/PixbufTimeNode.cs
index d465b3a..2c627b7 100644
--- a/LongoMatch/Time/PixbufTimeNode.cs
+++ b/LongoMatch/Time/PixbufTimeNode.cs
@@ -35,8 +35,10 @@ namespace LongoMatch.TimeNodes
 		
 		public PixbufTimeNode(string name, Time start, Time stop, Pixbuf thumbnail): base (name,start,stop)
 		{
-			if (thumbnail != null)
+			if (thumbnail != null){
 				this.thumbnailBuf = thumbnail.SaveToBuffer("png");
+				thumbnail.Dispose();
+			}
 			else thumbnailBuf = null;
 		}
 		#endregion
diff --git a/libcesarplayer/src/bacon-video-widget-gst-0.10.c b/libcesarplayer/src/bacon-video-widget-gst-0.10.c
index 905acbc..b91a6c6 100644
--- a/libcesarplayer/src/bacon-video-widget-gst-0.10.c
+++ b/libcesarplayer/src/bacon-video-widget-gst-0.10.c
@@ -4976,6 +4976,11 @@ destroy_pixbuf (guchar *pix, gpointer data)
   gst_buffer_unref (GST_BUFFER (data));
 }
 
+void 
+bacon_video_widget_unref_pixbuf (GdkPixbuf *pixbuf){
+	g_object_unref(pixbuf);
+}
+
 /**
  * bacon_video_widget_get_current_frame:
  * @bvw: a #BaconVideoWidget
diff --git a/libcesarplayer/src/bacon-video-widget.h b/libcesarplayer/src/bacon-video-widget.h
index 14cdb5a..e25a8d1 100644
--- a/libcesarplayer/src/bacon-video-widget.h
+++ b/libcesarplayer/src/bacon-video-widget.h
@@ -419,6 +419,7 @@ EXPORT gboolean bacon_video_widget_has_previous_track	 (BaconVideoWidget *bvw);
 EXPORT gboolean bacon_video_widget_can_get_frames       (BaconVideoWidget *bvw,
 						  GError **error);
 EXPORT GdkPixbuf *bacon_video_widget_get_current_frame (BaconVideoWidget *bvw);
+EXPORT void bacon_video_widget_unref_pixbuf (GdkPixbuf *pixbuf);
 
 /* Audio-out functions */
 /**



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]