Final tweaks to improve Thumbnailing and now on CodePlex!

In the prior two posts, I talked about creating and fixing the logic for creating video thumbnails / screenshots but it had a few flaws in it.

The first was I didn’t realize I had to close the MediaPlayer object’s stream, this caused memory to balloon upward after multiple plays.  Another problem was opening the same file for the same screenshots could cause issues in the long run at the same time.  To solve these issues, one was an easy fix, the other required a bit of threading knowledge.

To correct this, I’ll first have a Dictionary object to pass in multiple TimeSpans so I can do multiple captures without having the file open multiple times.  I also created used a Mutex that is tied to the video’s Uri.  This will lock the thread until the other processing has been completed.  This will help reduce the memory load footprint in a threaded environment.  You still can get in trouble by opening up some very large video files in a threaded environment

To get access to the tester app, head over to codeplex and source code can be found there too!

public static void CaptureScreen(Uri source, 
	Dictionary<TimeSpan, object> captureList, 
	double scale, CaptureWorkerDelegate finalWorkerPrimary, 
	CaptureWorkerDelegate finalWorkerThumbnail)
{
	var mutexLock = new Mutex(false, source.GetHashCode().ToString());
	mutexLock.WaitOne();
	
	var player = new MediaPlayer { Volume = 0, ScrubbingEnabled = true };

	player.Open(source);
	player.Pause();
	foreach (var pair in captureList)
	{
		var timeSpan = pair.Key;
		var state = pair.Value;

		player.Position = timeSpan;
		Thread.Sleep(1000);

		var width = player.NaturalVideoWidth;
		var height = player.NaturalVideoHeight;

		var rtb = new RenderTargetBitmap(width, height, 96, 96, PixelFormats.Pbgra32);
		var dv = new DrawingVisual();

		using (DrawingContext dc = dv.RenderOpen())
			dc.DrawVideo(player, new Rect(0, 0, width, height));

		rtb.Render(dv);
		var frame = BitmapFrame.Create(rtb).GetCurrentValueAsFrozen();
		if (finalWorkerPrimary != null)
			finalWorkerPrimary(frame as BitmapFrame, state);

		if (scale > 0 && finalWorkerThumbnail != null)
		{
			var thumbnailFrame =
				BitmapFrame.Create(new TransformedBitmap(frame as BitmapSource, new ScaleTransform(scale, scale))).
					GetCurrentValueAsFrozen();
			var encoder = new JpegBitmapEncoder();
			encoder.Frames.Add(thumbnailFrame as BitmapFrame);

			finalWorkerThumbnail(thumbnailFrame as BitmapFrame, state);
		}
	}
	player.Close();
	mutexLock.ReleaseMutex();
}

No comments posted yet.

Post a Comment

Please add 7 and 4 and type the answer here: