Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-8236831

video stutter after playing same video over and over for a couple of hours

XMLWordPrintable

    • x86_64
    • linux_ubuntu

      ADDITIONAL SYSTEM INFORMATION :
      OS: Ubuntu 18.04.3 64 bit desktop

      Java Runtime:
      openjdk 11.0.4 2019-07-16
      OpenJDK Runtime Environment (build 11.0.4+11-post-Ubuntu-1ubuntu218.04.3)
      OpenJDK 64-Bit Server VM (build 11.0.4+11-post-Ubuntu-1ubuntu218.04.3, mixed mode, sharing)
      JavaFX: javafx-sdk-13.0.1


      A DESCRIPTION OF THE PROBLEM :
      On Ubuntu 18.04 I have a JavaFX 13 app that plays the same video over and over using javafx.scene.media.MediaPlayer and javafx.scene.media.MediaView. In each iteration it loads the MediaPlayer with same media via url and then plays it. At first the video plays smoothly but after about an hour it starts stuttering in my machine with 8GB of RAM and does not happen (at least in a few hours) in my machine with 32GB of RAM.

      Since its plays smooth initially I am guessing its not a codec issue. Since it gets worse with time I am guessing its a memory leak somewhere. Monitoring my JVM using visualvm it does not appear to be a memory or thread leak in my app.

      I tried the same test app with JavaFX 14-ea+4 and it seemed that it was worse than JavaFX 13.0.1 as it seemed the stutter started being noticeable in early cycle with 14 whereas with 13 it was noticeable after 20 minutes or so.

      Stackoverflow: https://stackoverflow.com/questions/59364435/javafx-video-stutter-after-playing-same-video-over-and-over-for-a-couple-of-hour

      STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
      0. Run an Ubuntu 18.04 64 bit machine / VM with 8GB of RAM (Important)
      1. Run attached java class specifying following JVM args:
      --module-path=/opt/javafx-sdk-13.0.1/lib --add-modules=javafx.controls,javafx.swing,javafx.media,javafx.graphics,javafx.web"
      2. Wait 1 hour

      EXPECTED VERSUS ACTUAL BEHAVIOR :
      EXPECTED -
      Video is playing smoothly
      ACTUAL -
      1. Video starts playing smoothly for first 15 minutes or so (good)
      2. After 45 minutes to an hour Video stops playing smoothly and stutters frequently (not good)

      ---------- BEGIN SOURCE ----------
      package javafxtest;

      import javafx.application.Application;
      import javafx.scene.Scene;
      import javafx.scene.layout.BorderPane;
      import javafx.scene.media.Media;
      import javafx.scene.media.MediaPlayer;
      import javafx.scene.media.MediaView;
      import javafx.stage.Stage;
      import javafx.util.Duration;
      import org.slf4j.Logger;
      import org.slf4j.LoggerFactory;

      import java.net.MalformedURLException;
      import java.net.URISyntaxException;
      import java.net.URL;

      public class JavaFxVideoTestApp extends Application {
          private static final Logger LOGGER = LoggerFactory.getLogger(JavaFxVideoTestApp.class);

          MediaPlayer mediaPlayer;
          MediaView mediaView;

          public static void main(String[] args) {
              Application.launch(args);
          }

          @Override
          public void start(Stage primaryStage) throws Exception {
              Thread.setDefaultUncaughtExceptionHandler(JavaFxVideoTestApp::showError);

              BorderPane borderPane = new BorderPane();
              Scene scene = new Scene(borderPane);
              primaryStage.setScene(scene);

              mediaView = new MediaView();
              borderPane.setCenter(mediaView);

              primaryStage.setFullScreen(true);
              primaryStage.show();

              loadEvent();
          }

          private static void showError(Thread thread, Throwable throwable) {
              LOGGER.error("Unhandled error. Thread: {}", thread.getName(), throwable);
          }

          public void loadEvent() throws MalformedURLException, URISyntaxException {
              String videoFileURI = (new URL("https://dl.dropboxusercontent.com/s/b8lyrt5r61oxxnc/job-chasing-his-illusive-dreams-dec-2017.mp4")).toURI().toString();

              // Create a new MediaPlayer
              resetMediaPlayer("loadEvent");

              Media media = new Media(videoFileURI);
              LOGGER.debug("LoadEvent new video loaded : {}", media.getSource());
              mediaPlayer = new MediaPlayer(media);
              mediaPlayer.setStartTime(Duration.ZERO);
              mediaPlayer.errorProperty().addListener((observable, oldValue, newValue) ->
                      LOGGER.error(String.format("MediaPlayer error. videoFileURI: %s error: '%s'", videoFileURI, newValue)));
              mediaPlayer.statusProperty().addListener((observable, oldValue, newValue) -> {
                  if (newValue == MediaPlayer.Status.READY) {
                      LOGGER.info("MediaPlayer status: Ready");
                      showEvent();
                  }
              });
              mediaPlayer.setCycleCount(1);
              mediaPlayer.setMute(true);
              mediaPlayer.setOnEndOfMedia(() -> {
                  try {
                      resetMediaPlayer("mediaPlayer.setOnEndOfMedia");
                      loadEvent();
                  } catch (MalformedURLException|URISyntaxException e) {
                      LOGGER.error("Error loading event", e);
                  }
              });
              mediaView.setMediaPlayer(mediaPlayer);
          }

          public void showEvent() {
              if (mediaPlayer != null) {
                  MediaPlayer.Status status = mediaPlayer.getStatus();
                  if (status == MediaPlayer.Status.READY || status == MediaPlayer.Status.STOPPED) {
                      mediaPlayer.setStartTime(Duration.ZERO);
                      mediaPlayer.setStopTime(mediaPlayer.getMedia().getDuration());
                      mediaPlayer.setCycleCount(MediaPlayer.INDEFINITE);
                      mediaPlayer.play();
                  }
              } else {
                  LOGGER.error("showEvent video mediaplayer NULL");
              }
          }

          private void resetMediaPlayer(String caller) {
              if (mediaPlayer != null) {
                  LOGGER.trace("resetMediaPlayer entered. caller: {}", caller);
                  try {
                      mediaPlayer.stop();
                  } catch (Exception e) {
                      LOGGER.warn("Error while stopping media player");
                  }
                  try {
                      mediaPlayer.dispose();
                  } catch (Exception e) {
                      LOGGER.warn("Error while disposing media player");
                  }
                  mediaPlayer = null;
              }
              mediaView.setMediaPlayer(null);
          }
      }

      ---------- END SOURCE ----------

      CUSTOMER SUBMITTED WORKAROUND :
      None known to submitter. Would really like to know one.

      FREQUENCY : always


            almatvee Alexander Matveev
            webbuggrp Webbug Group
            Votes:
            0 Vote for this issue
            Watchers:
            2 Start watching this issue

              Created:
              Updated: