I have an application that plays audio using NAudio. A well-known limitation with NAudio is that every time the garbage collector starts, every thread pauses until it is executed.
The application is working fine, all the GC runs in an acceptable amount of time, and there is no stuttering.
But we also have a separate application that sends a thumbnail to the main application (with a sound player) via TCP every second. The thumbnail is about 1300 bytes when encoded in JPEG format.
This is the code we use to decode the image:
MemoryStream ms = new MemoryStream(data); BitmapDecoder bdec = BitmapDecoder.Create(ms, BitmapCreateOptions.None, BitmapCacheOption.Default); BitmapSource source = bdec.Frames[0]; imgPreview.Source = source;
And for coding:
JpegBitmapEncoder jpgEncoder = new JpegBitmapEncoder(); jpgEncoder.QualityLevel = quality; jpgEncoder.Frames.Add(BitmapFrame.Create(renderTarget)); byte[] imageArray; using (MemoryStream outputStream = new MemoryStream()) { jpgEncoder.Save(outputStream); imageArray = outputStream.ToArray(); }
Where RenderTarget is a RenderTargetBitmap that has image content.
Now we create and discard MemoryStream, BitmapDecoder and BitmapSource every second. I commented out the lines from the code, and it looks like the MemoryStream and the BitmapDecoder constructor do not stutter, but after it is accessed through Frames [0] it starts to stutter.
We also tried this approach instead of BitmapDecoder, but with the same results:
img.BeginInit(); img.StreamSource = ms; img.EndInit();
Of course, is there a better way to keep the image up to date?
The best way is to simply send the raw image data and create a WriteableBitmap that is simply overwritten every second. But the original image is 170 kb, 100 times larger than the encoded image, and we really do not want to do this. Can I decode a JPEG stream into an existing byte array or an existing image?