We have a legacy application written using MFC/Win32 GDI whose primary function is to
display JPEG images from various sources (e.g. cameras) at a constant frame rate (which can
be up to 30 frames per second).
On a given target hardware our legacy app can display 20 "160x120" jpegs at 5 fps consuming
about 30-40% CPU. For JPEG decoding we use Intel's JPEG decoder which is based on
Intel's performance primitives.
We are planning to use WPF for our next version of the application. To compare the performance,
I wrote a simple app that displays 20 "160x120" jpegs at 5 fps. Now the CPU usage has doubled to about
70-80% on the same taraget hardware.
The legacy app used to first write to an in-memory bitmap and then would render the bitmap to
display - the classic double-bufferring solution. My test WPF app does not do any of that, it
just creates 20 "Image" objects and updates the "Src" attribute to the decoded JPEG image.
I use the JpegBitmapDecoder which is part of the WPF infrastructure libraries.
I would like to know if my rather naive solution in WPF is correct for the problem at hand If not,
I would appreciate any other alternative ways of doing this to get comparable or even better
performance. On thing to mention is, in the legacy app, the JPEG image is decoded on
the thread it is received in and rendered on a different thread. In my WPF app, I am not
sure where it gets decoded, but I believe it is in the UI thread (I use Dispatcher.BeginInvoke()).
To BeginInvoke, I pass the byte[] array containing the encoded JPEG image.
Below I have some snippets of the code to illustrate what I am doing:
Callback method called to handle an incoming JPEG:
public void onJPEGData(CMR_CLI.JPEG jpeg, Byte[] imgBuf, DateTime cap_time)
{
MemoryStream strm = new MemoryStream((Byte[])imgBuf);
img.Dispatcher.BeginInvoke
(
DispatcherPriority.Normal,
new UpdateImage(updateImage),
strm
);
Set JPEG image:
delegate void UpdateImage(Stream arg);
void updateImage(Stream strm)
{
BitmapDecoder dec = JpegBitmapDecoder.Create
(
strm,
BitmapCreateOptions.None,
BitmapCacheOption.None
);
foreach (BitmapFrame f in dec.Frames)
{
// img - System.Windows.Controls.Image
img.Source = f;
break;
}
}
Thanks & Kind regards
LMS