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

JavaFX Mediaplayer hang when seeking multiple videos at the same time

    XMLWordPrintable

    Details

    • Subcomponent:
    • CPU:
      x86_64
    • OS:
      windows_10

      Description

      A DESCRIPTION OF THE PROBLEM :
      I have 8 Mediaplayer playing at the same time. When I seek them at the same time > 50% of the time some videos hang. Sometimes (~30%) after a while they start playing again, but in slow-motion. onError is not called and getRate() = 1.

      STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
      Play 8 Mediaplayer at the same time, hook them up to the same controls and seek a few times.

      EXPECTED VERSUS ACTUAL BEHAVIOR :
      EXPECTED -
      Player all seek to the same time.
      ACTUAL -
      Player hang without error message. Some will continue at some point in a very slow speed.

      ---------- BEGIN SOURCE ----------
      package org.example;

      import javafx.application.Platform;
      import javafx.geometry.Insets;
      import javafx.geometry.Pos;
      import javafx.scene.Node;
      import javafx.scene.control.Button;
      import javafx.scene.control.Slider;
      import javafx.scene.layout.BorderPane;
      import javafx.scene.layout.HBox;
      import javafx.scene.layout.Pane;
      import javafx.scene.layout.Priority;
      import javafx.scene.media.MediaPlayer;
      import javafx.scene.media.MediaView;
      import javafx.stage.Window;
      import javafx.util.Duration;

      import java.util.ArrayList;
      import java.util.List;

      public class MediaControlMinimal extends BorderPane {

          private final List<MediaPlayer> mpList;
          private Duration duration;
          private boolean shouldPlay;
          private int setupComplete;

          private final Slider timeSlider;
          private final HBox mediaBar;
          private final Button playButton;
          private final MediaPlayer controlMediaPlayer;

          public MediaControlMinimal(List<MediaPlayer> mpList, int videoRows) {

              this.mpList = mpList;
              List<MediaView> mvList = new ArrayList<>(mpList.size());

              Pane mvPane = new Pane() {
              };

              for (MediaPlayer mp : mpList) {
                  MediaView mediaView = new MediaView(mp);
                  mvList.add(mediaView);
                  mvPane.getChildren().add(mediaView);
              }

              mvPane.setStyle("-fx-background-color: black;");
              setCenter(mvPane);

              mediaBar = new HBox(); // 5 als param für spacing = 5, sieh zeile 247
              mediaBar.setAlignment(Pos.CENTER);
              mediaBar.setPadding(new Insets(5, 10, 5, 10));
              BorderPane.setAlignment(mediaBar, Pos.CENTER);
              playButton = new Button();

              playButton.setOnAction(e -> {
                  shouldPlay = !shouldPlay;
                  if (shouldPlay) {
                      playAll();
                  } else {
                      pauseAll();
                  }
              });

              // Add time slider
              timeSlider = new Slider();
              HBox.setHgrow(timeSlider, Priority.ALWAYS);
              timeSlider.setMinWidth(50);
              timeSlider.setMaxWidth(Double.MAX_VALUE);

              timeSlider.setOnMouseReleased(event -> {
                  //timeSlider.setValueChanging(true);
                  //timeSlider.setValue((event.getX() / timeSlider.getWidth()) * timeSlider.getMax());
                  //timeSlider.setValueChanging(false);
                  System.out.println("setOnMouseReleased");
                  final Duration seekTo = Duration.millis((event.getX() / timeSlider.getWidth()) * timeSlider.getMax());
                  for (MediaPlayer mp : mpList) {
                      new Thread(() -> {
                      mp.seek(seekTo);
                      }).start();
                  }
              });

              controlMediaPlayer = mpList.get(1);
              controlMediaPlayer.currentTimeProperty().addListener((observable, oldVal, newVal) -> {
                  updateValues(controlMediaPlayer);
              });

              for (MediaPlayer mp : mpList) {
                  mp.setOnReady(() -> {
                      int videosPerRow = mpList.size() / videoRows;
                      if (setupComplete == 0) {
                          duration = mp.getMedia().getDuration();
                          timeSlider.setMax(duration.toMillis());
                          updateValues(mp);
                          final Window window = mvPane.getScene().getWindow();
                          final double titleHeight = window.getHeight() - mvPane.getScene().getHeight();
                          double windowHeight = videoRows * mp.getMedia().getHeight() + titleHeight;
                          if (!Main.isTransDesign) {
                              windowHeight += mediaBar.getHeight();
                          }
                          window.setHeight(windowHeight);
                          window.setWidth(videosPerRow * mp.getMedia().getWidth());
                      }

                      if (setupComplete < mpList.size()) {
                          final Node mpNode = mvPane.getChildren().get(mpList.indexOf(mp));
                          if (mpList.indexOf(mp) != 0 && mpNode.getLayoutX() == 0 && mpNode.getLayoutY() == 0) {
                              //fenster höhe
                              double xRelocate = mp.getMedia().getWidth() * (mpList.indexOf(mp) % videosPerRow);
                              double yRelocate = mp.getMedia().getHeight() * Math.floorDiv(mpList.indexOf(mp), videosPerRow);
                              mpNode.relocate(xRelocate, yRelocate);
                          }
                          ++setupComplete;
                      }
                  });
                  mp.setCycleCount(MediaPlayer.INDEFINITE);
              }

              mediaBar.getChildren().add(playButton);
              mediaBar.getChildren().add(timeSlider);
              setBottom(mediaBar);
          }

          private void playAll() {
              for (MediaPlayer mp : mpList) {
                  mp.play();
              }
          }


          private void pauseAll() {
              for (MediaPlayer mp : mpList) {
                  mp.pause();
              }
          }


          protected void updateValues(MediaPlayer mp) {
              if (timeSlider != null) {
                  Platform.runLater(() -> {
                      Duration currentTime = mp.getCurrentTime();
                      timeSlider.setDisable(duration.isUnknown());
                      if (!timeSlider.isDisabled() && duration.greaterThan(Duration.ZERO) && !timeSlider.isValueChanging()) {
                          timeSlider.setValue(currentTime.toMillis());
                      }
                  });
              }
          }
      }

      package org.example;

      import javafx.application.Application;
      import javafx.scene.Group;
      import javafx.scene.Scene;
      import javafx.scene.media.Media;
      import javafx.scene.media.MediaPlayer;
      import javafx.stage.Stage;

      import java.util.ArrayList;
      import java.util.List;

      public class EmbeddedMediaPlayer extends Application {

          @Override
          public void start(Stage primaryStage) {
              Group root = new Group();


              Scene scene = new Scene(root, 1586, 951);

              List<MediaPlayer> mediaPlayerList = new ArrayList<>();
              // create media player
              for(String s : Main.MEDIA_URL){
                  MediaPlayer mediaPlayer = new MediaPlayer(new Media(s));
                  mediaPlayer.setAutoPlay(false);
                  mediaPlayerList.add(mediaPlayer);
              }
           
              MediaControl mediaControl = new MediaControl(mediaPlayerList, Main.VIDEO_ROWS);
              scene.setRoot(mediaControl);
             
              primaryStage.setScene(scene);
              primaryStage.show();
          }

          @Override
          public void stop(){
             System.exit(0);
          }

          /**
           * The main() method is ignored in correctly deployed JavaFX application.
           * main() serves only as fallback in case the application can not be
           * launched through deployment artifacts, e.g., in IDEs with limited FX
           * support. NetBeans ignores main().
           *
           * @param args the command line arguments
           */
          public static void main(String[] args) {
              launch(args);
          }
      }

      package org.example;

      import java.io.File;
      import java.io.FileNotFoundException;
      import java.util.ArrayList;
      import java.util.List;
      import java.util.Scanner;

      public class Main {

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

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

      CUSTOMER SUBMITTED WORKAROUND :
      Not really a workaround, but it will make the bug reappear less often: start every seek in a new Thread.

      FREQUENCY : often


        Attachments

          Activity

            People

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

              Dates

              Created:
              Updated: