I'm building a video player in pure Java around JMF, with completely custom UI controls. Everything was working great until I put in a JLabel which updates the current play time in hh:mm:ss.ss format. The label updates acceptably, but occasionally halts for 10+ seconds at at a time, which is unacceptable.
The JMF Player
is created in a SwingUtilities.invokeLater(new Runnable()...
block. Here is the UI updating code:
protected void createUIUpdater() {
System.out.println("Creating UI updating worker thread");
new Thread() {
@Override
public void run() {
while(mediaPlayer.getState() == Controller.Started) {
updatePlayPosition();
try {
Thread.sleep(100);
} catch (InterruptedException e) {
System.err.println("Sleep interrupted!");
}
}
System.out.println("UI Updater thread finished.");
}
}.start();
}
protected void updatePlayPosition() {
Movie movie = timelineEditor.getMovie();
movie.setInsertionPoint(Rational.valueOf(mediaPlayer.getMediaTime().getSeconds()));
updateTimeLabel();
}
protected void updateTimeLabel() {
Movie movie = timelineEditor.getMovie();
Rational time = movie == null ? new Rational(0,1) : movie.getInsertionPoint();
// ... hours/minutes/seconds calculated
timeLabel.setText((hours < 10 ? "0" + hours : hours) + ":" + (minutes < 10 ? "0" + minutes : minutes)
+ ":" + (seconds < 10 ? "0" + seconds : seconds)
+ "." + (frame < 10 ? "0" + frame : frame));
}
which is called in a ControllerListener
on a StartEvent
. During this time the audio/video are playing.
I'm admittedly a bit of a novice when it comes to concurrency in Java, and I'm sure there's a better way of handling this separate thread. Any suggestions?
After closer inspection, it seems that my thread is executing fine, it is just getting blocked occasionally on mediaPlayer.getMediaTime()
(where mediaPlayer
is a javax.media.Player
).
Turns out, calling mediaPlayer.getMediaNanoseconds()
does not block.