javaFX: MediaPlayer's seek method hangs the player without error message oder Status change

那年仲夏 提交于 2020-12-26 08:32:13

问题


I have a programm with 8 mediaplayer, which are controlled like one big video with a single set of controls.

I have one Slider to control the time, aka I call all MediaPlayer's seek methods in onMouseReleased of the slider. My Problem is, the mediaplayer hang all the time, without changing their status or calling onError . When I put every seek in a new Thread, these problems disappear msot of the time, but not always and I'm gettign a lot of concurrency issues.

Does anybody know the reason why the player hangs?

EDIT: Ok, here a minimal reproducible example:

Class MediaControlMinimal:

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 -> {          
        for (MediaPlayer mp : mpList) {
            mp.seek(Duration.millis((event.getX() / timeSlider.getWidth()) * timeSlider.getMax());
        }
    });

    controlMediaPlayer = mpList.get(1);
    controlMediaPlayer.currentTimeProperty().addListener(observable -> {
        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());
            }
        });
    }
}
}

Class EmbeddedMediaPlayer

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) {

    primaryStage.setTitle(Main.WINDOW_TITLE);
    Group root = new Group();
    Scene scene = new Scene(root, 1586, 900);

    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);
    }
    MediaControlMinimal mediaControl = new MediaControlMinimal(mediaPlayerList, Main.VIDEO_ROWS); 
    scene.setRoot(mediaControl);
    primaryStage.setScene(scene);
    primaryStage.show();
}

@Override
public void stop(){
    System.out.println("Stage is closing");
   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);
}
}

Class Main

package org.example;
public class Main {

public static final String[] MEDIA_URL = {
        "https://video.fogodosamba.de/media/SambaReggae_Sticks.mp4",
        "https://video.fogodosamba.de/media/SambaReggae_Fundo1.mp4",
        "https://video.fogodosamba.de/media/SambaReggae_Dobra.mp4",
        "https://video.fogodosamba.de/media/SambaReggae_Fundo2.mp4",
        "https://video.fogodosamba.de/media/SambaReggae_Ansage.mp4",
        "https://video.fogodosamba.de/media/SambaReggae_Timbal.mp4",
        "https://video.fogodosamba.de/media/SambaReggae_Caixa.mp4",
        "https://video.fogodosamba.de/media/SambaReggae_Repi.mp4"
};
public static final int VIDEO_ROWS = 2; 
public static final String WINDOW_TITLE = ""; 

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

EDIT 2:

Sometimes a video hsngs for a while, then starts up again, but plays in slow motion. No error message in onerror, no state change and getCurrentRate = 1.

来源:https://stackoverflow.com/questions/65064419/javafx-mediaplayers-seek-method-hangs-the-player-without-error-message-oder-st

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!