Thread Slows Down After First Run
Hello, I'm working on a little experimental program that displays an image sequence as if it were
a video. Everything works great except that after the first play of the video it begins to slow down
and appears to be choppy. At first run it displays the images at 29.97 fps with no problem, but after
that it drops down to maybe < 20 fps. This is my first time working with threads so any help
would be greatly appreciated. Thanks!
Code:
import java.awt.*;
import java.awt.event.*;
import java.util.*;
import javax.swing.*;
import java.awt.image.BufferedImage;
import java.io.File;
import javax.imageio.ImageIO;
public class ImageSequenceViewer extends JFrame
implements ActionListener, Runnable {
private JButton startButton;
private JButton stopButton;
private JPanel canvas;
private Thread runner;
private volatile boolean isPlaying;
private BufferedImage[] video;
private volatile int curFrame;
private int pause;
private double fps = 29.97;
private double frameDuration;
public static void main(String[] args) {
ImageSequenceViewer viewer = new ImageSequenceViewer();
viewer.loadImageSequence();
}
public ImageSequenceViewer() {
super("ImageSequenceViewer");
setDefaultCloseOperation(EXIT_ON_CLOSE);
Container pane = getContentPane();
isPlaying = false;
curFrame = 0;
frameDuration = 1.0 / fps;
pause = (int) (frameDuration * 1000.0);
canvas = new JPanel();
pane.add(canvas, BorderLayout.CENTER);
startButton = new JButton("Start");
stopButton = new JButton("Stop");
JPanel panel = new JPanel();
panel.add(startButton);
startButton.addActionListener(this);
panel.add(stopButton);
stopButton.addActionListener(this);
pane.add(panel, BorderLayout.SOUTH);
setBounds(0, 0, 500, 500);
setVisible(true);
}
public void loadImageSequence()
{
JFileChooser fc = new JFileChooser();
fc.setMultiSelectionEnabled(true);
fc.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
fc.showOpenDialog(null);
File directory = fc.getSelectedFile();
if (directory.isDirectory()) {
File[] children = directory.listFiles();
video = new BufferedImage[children.length];
File file;
for (int i = 0; i < children.length; i++) {
file = children[i];
BufferedImage img = null;
try {
img = ImageIO.read(file);
} catch (Exception e) {
img = new BufferedImage(500, 500, BufferedImage.TYPE_INT_ARGB);
}
video[i] = img;
}
}
}
public void actionPerformed(ActionEvent ae) {
Object source = ae.getSource();
if (source == startButton) {
if (!isPlaying) {
runner = new Thread(this);
runner.start();
isPlaying = true;
}
} else if (source == stopButton) {
if (runner != null && isPlaying) {
runner.interrupt();
isPlaying = false;
}
}
}
public void run() {
Graphics g = canvas.getGraphics();
while (isPlaying) {
g.drawImage(video[curFrame], 0, 0, null);
curFrame++;
curFrame %= video.length;
pause(pause);
}
g.dispose();
}
public void pause(int milliseconds) {
try {
Thread.sleep(milliseconds);
} catch (InterruptedException e) {
System.out.println("Paused");
}
}
}