Search code examples
javaconcurrencyjmf

Java Concurrency issues when updating video control UI while JMF video is playing


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?


Solution

  • 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.