I'm writing an application to play back an image sequence of varying size (possibly 1000+ images) at variable FPS (up to 120), and while my current solution works for a small amount of images, it eats up memory very quickly (playing ~109mb of images takes ~526mb of Process Memory, and it seems to increase exponentially) and if given a large amount of images will produce an OutOfMemoryException.
My MainWindow and VideoViewer classes look like this -
MainWindow:
public partial class MainWindow : Window
{
OpenFileDialog openFileDialog1 = new OpenFileDialog();
VideoViewer vV = new VideoViewer();
DispatcherTimer timer = new DispatcherTimer();
public MainWindow()
{
InitializeComponent();
this.DataContext = vV;
}
private void PlayButton_Click(object sender, RoutedEventArgs e)
{
timer = new DispatcherTimer { Interval = TimeSpan.FromSeconds(1f/120f) };
timer.Tick += TimerTick;
timer.Start();
}
private void PauseButton_Click(object sender, RoutedEventArgs e)
{
timer.Stop();
}
private void TimerTick(object sender, EventArgs e)
{
vV.NextFrame();
}
private void BrowseButton_Click(object sender, RoutedEventArgs e)
{
// Set the file dialog to filter for graphics files.
this.openFileDialog1.Filter =
"Images (*.BMP;*.JPG;*.GIF;*.PNG)|*.BMP;*.JPG;*.GIF;*.PNG|" +
"All files (*.*)|*.*";
// Allow the user to select multiple images.
this.openFileDialog1.Multiselect = true;
this.openFileDialog1.Title = "My Image Browser";
DialogResult dr = this.openFileDialog1.ShowDialog();
if (dr == System.Windows.Forms.DialogResult.OK)
{
if (dr == System.Windows.Forms.DialogResult.OK)
{
List<ImageSource> images = new List<ImageSource>();
// Read the files
foreach (String file in openFileDialog1.FileNames)
{
var fullFilePath = @file;
//Create a new bitmap to assign our image to
BitmapImage bitmap = new BitmapImage();
bitmap.BeginInit();
bitmap.CreateOptions = BitmapCreateOptions.IgnoreImageCache;
bitmap.CacheOption = BitmapCacheOption.None;
bitmap.UriSource = new Uri(fullFilePath, UriKind.Absolute);
bitmap.EndInit();
images.Add(bitmap);
}
vV.imagesArray = images;
}
}
}
}
VideoViewer:
public class VideoViewer : INotifyPropertyChanged
{
private ImageSource image;
private List<ImageSource> imageLocs = new List<ImageSource>();
private int imageIndex = 0;
public event PropertyChangedEventHandler PropertyChanged;
public ImageSource imageSource
{
get
{
return image;
}
set
{
image = value;
OnPropertyChanged("imageSource");
}
}
public List<ImageSource> imagesArray
{
get
{
return imageLocs;
}
set
{
imageLocs = value;
OnPropertyChanged("imagesArray");
}
}
public void NextFrame()
{
//If not on first or last frame
if(imageIndex < (imageLocs.Count - 1))
{
imageIndex += 1;
imageSource = imagesArray[imageIndex];
OnPropertyChanged("imageSource");
}
else if(imageIndex == (imageLocs.Count - 1))
{
imageIndex = 0;
imageSource = imagesArray[imageIndex];
OnPropertyChanged("imageSource");
}
}
// Create the OnPropertyChanged method to raise the event
protected void OnPropertyChanged(string name)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
}
}
When playing the sequence, the first loop plays back slowly, and this is where the memory is taken up. After the first loop, it plays back at the desired speed and the memory sits at a constant value, which leads me to think it's something to do with the caching of the images.
As you can see I've tried adjusting the caching options of the bitmap image but it didn't make a difference. I'm also currently building to x64 to give myself extra memory to use.
Is it possible to reduce the memory usage while keeping the playback speed?