Browse Source

new media player based on vlcj [Part 1]

* openjfx 12.0.2 -> 14
* log4j 2.13.0 -> 2.13.1
* maven-shade-plugin 3.2.1 -> 3.2.2
dev
Jannik 2 years ago
parent
commit
4184e982ea
Signed by: Seil0
GPG Key ID: E8459F3723C52C24
  1. 18
      pom.xml
  2. 2
      src/main/java/kellerkinder/HomeFlix/application/Main.java
  3. 172
      src/main/java/kellerkinder/HomeFlix/player/HFMediaPlayerEventListener.java
  4. 115
      src/main/java/kellerkinder/HomeFlix/player/NewMediaPlayer.java
  5. 33
      src/main/java/kellerkinder/HomeFlix/player/Player.java
  6. 192
      src/main/java/kellerkinder/HomeFlix/player/PlayerController.java
  7. 3
      src/main/resources/fxml/PlayerWindow.fxml

18
pom.xml

@ -27,19 +27,25 @@
<dependency>
<groupId>org.openjfx</groupId>
<artifactId>javafx-controls</artifactId>
<version>12.0.2</version>
<version>14</version>
</dependency>
<dependency>
<groupId>org.openjfx</groupId>
<artifactId>javafx-fxml</artifactId>
<version>12.0.2</version>
<version>14</version>
</dependency>
<dependency>
<groupId>org.openjfx</groupId>
<artifactId>javafx-media</artifactId>
<version>12.0.2</version>
<version>14</version>
</dependency>
<dependency>
<groupId>uk.co.caprica</groupId>
<artifactId>vlcj</artifactId>
<version>4.4.0</version>
</dependency>
<dependency>
@ -69,13 +75,13 @@
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-api</artifactId>
<version>2.13.0</version>
<version>2.13.1</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>2.13.0</version>
<version>2.13.1</version>
</dependency>
</dependencies>
@ -114,7 +120,7 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.2.1</version>
<version>3.2.2</version>
<configuration>
<finalName>Project-HomeFlix</finalName>
<shadedArtifactAttached>true</shadedArtifactAttached>

2
src/main/java/kellerkinder/HomeFlix/application/Main.java

@ -46,6 +46,8 @@ public class Main extends Application {
public static final String version = "0.8.0";
public static final String buildNumber = "173";
public static final String versionName = "toothless dragon";
// TODO rename streamURL to mediaURL
@Override
public void start(Stage primaryStage) throws IOException {

172
src/main/java/kellerkinder/HomeFlix/player/HFMediaPlayerEventListener.java

@ -0,0 +1,172 @@
/**
* Project-HomeFlix
*
* Copyright 2016-2020 <seil0@mosad.xyz>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA.
*
*/
package kellerkinder.HomeFlix.player;
import uk.co.caprica.vlcj.media.MediaRef;
import uk.co.caprica.vlcj.media.TrackType;
import uk.co.caprica.vlcj.player.base.MediaPlayer;
import uk.co.caprica.vlcj.player.base.MediaPlayerEventListener;
public class HFMediaPlayerEventListener implements MediaPlayerEventListener {
@Override
public void mediaChanged(MediaPlayer mediaPlayer, MediaRef media) {
// Auto-generated method stub
}
@Override
public void opening(MediaPlayer mediaPlayer) {
// Auto-generated method stub
}
@Override
public void buffering(MediaPlayer mediaPlayer, float newCache) {
// Auto-generated method stub
}
@Override
public void playing(MediaPlayer mediaPlayer) {
// Auto-generated method stub
}
@Override
public void paused(MediaPlayer mediaPlayer) {
// Auto-generated method stub
}
@Override
public void stopped(MediaPlayer mediaPlayer) {
// Auto-generated method stub
}
@Override
public void forward(MediaPlayer mediaPlayer) {
// Auto-generated method stub
}
@Override
public void backward(MediaPlayer mediaPlayer) {
// Auto-generated method stub
}
@Override
public void finished(MediaPlayer mediaPlayer) {
// Auto-generated method stub
}
@Override
public void timeChanged(MediaPlayer mediaPlayer, long newTime) {
// Auto-generated method stub
}
@Override
public void positionChanged(MediaPlayer mediaPlayer, float newPosition) {
// Auto-generated method stub
}
@Override
public void seekableChanged(MediaPlayer mediaPlayer, int newSeekable) {
// Auto-generated method stub
}
@Override
public void pausableChanged(MediaPlayer mediaPlayer, int newPausable) {
// Auto-generated method stub
}
@Override
public void titleChanged(MediaPlayer mediaPlayer, int newTitle) {
// Auto-generated method stub
}
@Override
public void snapshotTaken(MediaPlayer mediaPlayer, String filename) {
// Auto-generated method stub
}
@Override
public void lengthChanged(MediaPlayer mediaPlayer, long newLength) {
// Auto-generated method stub
}
@Override
public void videoOutput(MediaPlayer mediaPlayer, int newCount) {
// Auto-generated method stub
}
@Override
public void scrambledChanged(MediaPlayer mediaPlayer, int newScrambled) {
// Auto-generated method stub
}
@Override
public void elementaryStreamAdded(MediaPlayer mediaPlayer, TrackType type, int id) {
// Auto-generated method stub
}
@Override
public void elementaryStreamDeleted(MediaPlayer mediaPlayer, TrackType type, int id) {
// Auto-generated method stub
}
@Override
public void elementaryStreamSelected(MediaPlayer mediaPlayer, TrackType type, int id) {
// Auto-generated method stub
}
@Override
public void corked(MediaPlayer mediaPlayer, boolean corked) {
// Auto-generated method stub
}
@Override
public void muted(MediaPlayer mediaPlayer, boolean muted) {
// Auto-generated method stub
}
@Override
public void volumeChanged(MediaPlayer mediaPlayer, float volume) {
// Auto-generated method stub
}
@Override
public void audioDeviceChanged(MediaPlayer mediaPlayer, String audioDevice) {
// Auto-generated method stub
}
@Override
public void chapterChanged(MediaPlayer mediaPlayer, int newChapter) {
// Auto-generated method stub
}
@Override
public void error(MediaPlayer mediaPlayer) {
// Auto-generated method stub
}
@Override
public void mediaPlayerReady(MediaPlayer mediaPlayer) {
// Auto-generated method stub
}
}

115
src/main/java/kellerkinder/HomeFlix/player/NewMediaPlayer.java

@ -0,0 +1,115 @@
package kellerkinder.HomeFlix.player;
import java.nio.ByteBuffer;
import javafx.application.Platform;
import javafx.scene.Scene;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.image.PixelBuffer;
import javafx.scene.image.PixelFormat;
import javafx.scene.image.WritableImage;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;
import kellerkinder.HomeFlix.application.Main;
import uk.co.caprica.vlcj.factory.MediaPlayerFactory;
import uk.co.caprica.vlcj.player.base.MediaPlayer;
import uk.co.caprica.vlcj.player.embedded.EmbeddedMediaPlayer;
import uk.co.caprica.vlcj.player.embedded.videosurface.CallbackVideoSurface;
import uk.co.caprica.vlcj.player.embedded.videosurface.VideoSurfaceAdapters;
import uk.co.caprica.vlcj.player.embedded.videosurface.callback.BufferFormat;
import uk.co.caprica.vlcj.player.embedded.videosurface.callback.BufferFormatCallback;
import uk.co.caprica.vlcj.player.embedded.videosurface.callback.RenderCallback;
import uk.co.caprica.vlcj.player.embedded.videosurface.callback.format.RV32BufferFormat;
public class NewMediaPlayer {
private MediaPlayerFactory mediaPlayerFactory;
private EmbeddedMediaPlayer embeddedMediaPlayer;
private WritableImage videoImage;
private PixelBuffer<ByteBuffer> videoPixelBuffer;
private ImageView videoImageView;
private Stage stage;
private StackPane pane;
private Scene scene;
public NewMediaPlayer() {
mediaPlayerFactory = new MediaPlayerFactory();
embeddedMediaPlayer = mediaPlayerFactory.mediaPlayers().newEmbeddedMediaPlayer();
embeddedMediaPlayer.videoSurface().set(new FXCallbackVideoSurface());
}
public void init() {
// Auto-generated method stub
stage = new Stage();
pane = new StackPane();
scene = new Scene(pane);
videoImageView = new ImageView();
videoImageView.setPreserveRatio(true);
videoImageView.fitWidthProperty().bind(pane.widthProperty());
videoImageView.fitHeightProperty().bind(pane.heightProperty());
pane.getChildren().add(videoImageView);
stage.setScene(scene);
stage.setTitle("HomeFlix");
stage.getIcons().add(new Image(Main.class.getResourceAsStream("/icons/Homeflix_Icon_64x64.png")));
stage.setOnCloseRequest(event -> {
//DBController.getInstance().setCurrentTime(streamURL, playerController.getCurrentTime());
//playerController.getMediaPlayer().stop();
stop();
stage.close();
});
stage.show();
}
public void play(String streamURL) {
embeddedMediaPlayer.media().play(streamURL);
}
public void stop() {
embeddedMediaPlayer.controls().stop();
embeddedMediaPlayer.release();
mediaPlayerFactory.release();
System.out.println("released");
}
private class FXCallbackVideoSurface extends CallbackVideoSurface {
FXCallbackVideoSurface() {
super(new FXBufferFormatCallback(), new FXRenderCallback(), true,
VideoSurfaceAdapters.getVideoSurfaceAdapter());
}
}
private class FXBufferFormatCallback implements BufferFormatCallback {
private int sourceWidth;
private int sourceHeight;
@Override
public BufferFormat getBufferFormat(int sourceWidth, int sourceHeight) {
this.sourceWidth = sourceWidth;
this.sourceHeight = sourceHeight;
return new RV32BufferFormat(sourceWidth, sourceHeight);
}
@Override
public void allocatedBuffers(ByteBuffer[] buffers) {
assert buffers[0].capacity() == sourceWidth * sourceHeight * 4;
PixelFormat<ByteBuffer> pixelFormat = PixelFormat.getByteBgraPreInstance();
videoPixelBuffer = new PixelBuffer<>(sourceWidth, sourceHeight, buffers[0], pixelFormat);
videoImage = new WritableImage(videoPixelBuffer);
videoImageView.setImage(videoImage);
}
}
private class FXRenderCallback implements RenderCallback {
@Override
public void display(MediaPlayer mediaPlayer, ByteBuffer[] nativeBuffers, BufferFormat bufferFormat) {
Platform.runLater(() -> {
videoPixelBuffer.updateBuffer(pb -> null);
});
}
}
}

33
src/main/java/kellerkinder/HomeFlix/player/Player.java

@ -1,7 +1,7 @@
/**
* Project-HomeFlix
*
* Copyright 2016-2019 <@Seil0>
* Copyright 2016-2020 <seil0@mosad.xyz>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -36,9 +36,10 @@ import javafx.fxml.FXMLLoader;
import javafx.scene.Scene;
import javafx.scene.image.Image;
import javafx.scene.layout.AnchorPane;
import javafx.scene.layout.Pane;
import javafx.stage.Stage;
import kellerkinder.HomeFlix.application.Main;
import kellerkinder.HomeFlix.controller.DBController;
public class Player {
private PlayerController playerController;
@ -54,21 +55,20 @@ public class Player {
* @param currentTableFilm the currently selected film
*/
public Player(String streamURL) {
if (isSupportedFormat(streamURL)) {
hfPlayer(streamURL);
} else {
try {
newHFPlayer(streamURL);
} catch (Exception e) {
LOGGER.error("Error while playing media", e);
legacyPlayer(streamURL);
}
}
/**
* start the integrated player
* @param streamURL
*/
private void hfPlayer(String streamURL) {
playerController = new PlayerController(this, streamURL);
private void newHFPlayer(String mediaURL) {
playerController = new PlayerController(this, mediaURL);
try {
FXMLLoader fxmlLoader = new FXMLLoader();
@ -81,15 +81,14 @@ public class Player {
stage.setTitle("HomeFlix");
stage.getIcons().add(new Image(Main.class.getResourceAsStream("/icons/Homeflix_Icon_64x64.png")));
stage.setOnCloseRequest(event -> {
DBController.getInstance().setCurrentTime(streamURL, playerController.getCurrentTime());
playerController.getMediaPlayer().stop();
playerController.stop2();
stage.close();
});
playerController.init();
stage.setFullScreen(true);
//stage.setFullScreen(true);
stage.show();
playerController.init2();
playerController.start2();
} catch (Exception e) {
e.printStackTrace();
}
@ -158,4 +157,8 @@ public class Player {
return scene;
}
public Pane getPane() {
return pane;
}
}

192
src/main/java/kellerkinder/HomeFlix/player/PlayerController.java

@ -1,7 +1,7 @@
/**
* Project-HomeFlix
*
* Copyright 2016-2019 <@Seil0>
* Copyright 2016-2020 <seil0@mosad.xyz>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -22,15 +22,14 @@
package kellerkinder.HomeFlix.player;
import java.io.File;
import java.nio.ByteBuffer;
import java.util.Timer;
import java.util.TimerTask;
import com.jfoenix.controls.JFXButton;
import com.jfoenix.controls.JFXSlider;
import javafx.beans.binding.Bindings;
import javafx.beans.property.DoubleProperty;
import javafx.application.Platform;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.event.ActionEvent;
@ -39,21 +38,34 @@ import javafx.fxml.FXML;
import javafx.scene.Cursor;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.image.PixelBuffer;
import javafx.scene.image.PixelFormat;
import javafx.scene.image.WritableImage;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;
import javafx.scene.media.Media;
import javafx.scene.media.MediaPlayer;
import javafx.scene.media.MediaPlayer.Status;
import javafx.scene.media.MediaView;
import javafx.util.Duration;
import kellerkinder.HomeFlix.controller.DBController;
import kellerkinder.HomeFlix.controller.XMLController;
import kellerkinder.HomeFlix.datatypes.FilmTabelDataType;
import uk.co.caprica.vlcj.factory.MediaPlayerFactory;
import uk.co.caprica.vlcj.player.embedded.EmbeddedMediaPlayer;
import uk.co.caprica.vlcj.player.embedded.videosurface.CallbackVideoSurface;
import uk.co.caprica.vlcj.player.embedded.videosurface.VideoSurfaceAdapters;
import uk.co.caprica.vlcj.player.embedded.videosurface.callback.BufferFormat;
import uk.co.caprica.vlcj.player.embedded.videosurface.callback.BufferFormatCallback;
import uk.co.caprica.vlcj.player.embedded.videosurface.callback.RenderCallback;
import uk.co.caprica.vlcj.player.embedded.videosurface.callback.format.RV32BufferFormat;
public class PlayerController {
@FXML private MediaView mediaView;
@FXML private ImageView videoImageView;
@FXML private VBox bottomVBox;
@ -72,13 +84,19 @@ public class PlayerController {
private Player player;
private Media media;
private MediaPlayer mediaPlayer;
private MediaPlayer mediaPlayer2;
private MediaPlayerFactory mediaPlayerFactory;
private EmbeddedMediaPlayer embeddedMediaPlayer;
private WritableImage videoImage;
private PixelBuffer<ByteBuffer> videoPixelBuffer;
private FilmTabelDataType film;
private double currentTime = 0;
private double seekTime = 0;
private double startTime = 0;
private double duration = 0;
private long currentTime = 0;
private long seekTime = 0;
private long startTime = 0;
private long duration = 0;
private int season = 0;
private int episode = 0;
private int countdown = 0;
@ -100,7 +118,62 @@ public class PlayerController {
public PlayerController(Player player, String streamURL) {
this.player = player;
this.film = DBController.getInstance().getStream(streamURL);
mediaPlayerFactory = new MediaPlayerFactory();
embeddedMediaPlayer = mediaPlayerFactory.mediaPlayers().newEmbeddedMediaPlayer();
embeddedMediaPlayer.videoSurface().set(new FXCallbackVideoSurface());
}
public void init2() {
// initialize the image view
videoImageView.setPreserveRatio(true);
videoImageView.fitWidthProperty().bind(player.getStage().widthProperty());
videoImageView.fitHeightProperty().bind(player.getStage().heightProperty());
// set needed variables
startTime = (long) DBController.getInstance().getCurrentTime(film.getStreamUrl());
autoplay = XMLController.isAutoplay();
season = !film.getSeason().isEmpty() ? Integer.parseInt(film.getSeason()) : 0;
episode = !film.getEpisode().isEmpty() ? Integer.parseInt(film.getEpisode()) : 0;
initActions2();
}
private void initActions2() {
embeddedMediaPlayer.events().addMediaPlayerEventListener( new HFMediaPlayerEventListener() {
@Override
public void timeChanged(uk.co.caprica.vlcj.player.base.MediaPlayer mediaPlayer, long newTime) {
timeSlider.setValue((newTime / 1000) / 60);
}
@Override
public void error(uk.co.caprica.vlcj.player.base.MediaPlayer mediaPlayer) {
// Auto-generated method stub
}
@Override
public void lengthChanged(uk.co.caprica.vlcj.player.base.MediaPlayer mediaPlayer, long newLength) {
duration = newLength;
timeSlider.setMax((duration / 1000) / 60);
}
});
}
public void start2() {
embeddedMediaPlayer.media().play(film.getStreamUrl());
embeddedMediaPlayer.controls().skipTime((long) startTime);
}
public void stop2() {
DBController.getInstance().setCurrentTime(film.getStreamUrl(), embeddedMediaPlayer.status().time());
embeddedMediaPlayer.controls().stop();
embeddedMediaPlayer.release();
mediaPlayerFactory.release();
}
/**
* initialize the PlayerWindow
@ -108,54 +181,27 @@ public class PlayerController {
public void init() {
initActions();
if (film.getStreamUrl().startsWith("http")) {
media = new Media(film.getStreamUrl());
} else {
media = new Media(new File(film.getStreamUrl()).toURI().toString());
}
// create the MediaPlayer object
mediaPlayer = new MediaPlayer(media);
mediaView.setPreserveRatio(true);
mediaView.setMediaPlayer(mediaPlayer);
final DoubleProperty width = mediaView.fitWidthProperty();
final DoubleProperty height = mediaView.fitHeightProperty();
width.bind(Bindings.selectDouble(mediaView.sceneProperty(), "width"));
height.bind(Bindings.selectDouble(mediaView.sceneProperty(), "height"));
startTime = DBController.getInstance().getCurrentTime(film.getStreamUrl());
autoplay = XMLController.isAutoplay();
season = !film.getSeason().isEmpty() ? Integer.parseInt(film.getSeason()) : 0;
episode = !film.getEpisode().isEmpty() ? Integer.parseInt(film.getEpisode()) : 0;
initMediaPlayer();
// set the control elements to the correct value
playIcon.setImage(pause);
fullscreenIcon.setImage(fullscreenExit);
timeSlider.setValue(0);
}
private void initMediaPlayer() {
// start the media if the player is ready
mediaPlayer.setOnReady(new Runnable() {
mediaPlayer2.setOnReady(new Runnable() {
@Override
public void run() {
duration = media.getDuration().toMillis();
duration = (long) media.getDuration().toMillis();
timeSlider.setMax((duration / 1000) / 60);
mediaPlayer.play();
mediaPlayer.seek(Duration.millis(startTime));
mediaPlayer2.play();
mediaPlayer2.seek(Duration.millis(startTime));
}
});
// every time the play time changes execute this
mediaPlayer.currentTimeProperty().addListener(new ChangeListener<Duration>() {
mediaPlayer2.currentTimeProperty().addListener(new ChangeListener<Duration>() {
@Override
public void changed(ObservableValue<? extends Duration> observable, Duration oldValue, Duration newValue) {
currentTime = newValue.toMillis(); // set the current time
currentTime = (long) newValue.toMillis(); // set the current time
double timeToEnd = (duration - currentTime);
if (timeToEnd < 20000 && episode != 0 && autoplay) {
@ -176,7 +222,7 @@ public class PlayerController {
}
} else if (timeToEnd < 120) {
// if we are 120ms to the end stop the media
mediaPlayer.stop();
mediaPlayer2.stop();
DBController.getInstance().setCurrentTime(film.getStreamUrl(), 0); // reset old video start time
playIcon.setImage(playArrow);
} else {
@ -232,7 +278,7 @@ public class PlayerController {
timeSlider.setOnMouseReleased(new EventHandler<MouseEvent>() {
@Override
public void handle(MouseEvent event) {
mediaPlayer.seek(new Duration(seekTime));
mediaPlayer2.seek(new Duration(seekTime));
mousePressed = false;
}
});
@ -248,15 +294,14 @@ public class PlayerController {
timeSlider.valueProperty().addListener(new ChangeListener<Number>() {
@Override
public void changed(ObservableValue<? extends Number> ov, Number old_val, Number new_val) {
seekTime = (double) new_val * 1000 * 60;
seekTime = (long) ((double) new_val * 1000 * 60);
}
});
}
@FXML
void stopBtnAction(ActionEvent event) {
DBController.getInstance().setCurrentTime(film.getStreamUrl(), currentTime);
mediaPlayer.stop();
stop2();
player.getStage().close();
}
@ -273,11 +318,11 @@ public class PlayerController {
@FXML
void playBtnAction(ActionEvent event) {
if (mediaPlayer.getStatus().equals(Status.PLAYING)) {
mediaPlayer.pause();
if (embeddedMediaPlayer.status().isPlaying()) {
embeddedMediaPlayer.controls().pause();
playIcon.setImage(playArrow);
} else {
mediaPlayer.play();
embeddedMediaPlayer.controls().play();
playIcon.setImage(pause);
}
}
@ -292,7 +337,7 @@ public class PlayerController {
DBController.getInstance().setCurrentTime(film.getStreamUrl(), 0); // reset old video start time
FilmTabelDataType nextFilm = DBController.getInstance().getNextEpisode(film.getTitle(), episode, season);
if (nextFilm != null) {
mediaPlayer.stop();
mediaPlayer2.stop();
film = nextFilm;
init();
autoplay = true;
@ -300,11 +345,52 @@ public class PlayerController {
}
public MediaPlayer getMediaPlayer() {
return mediaPlayer;
return mediaPlayer2;
}
public double getCurrentTime() {
return currentTime;
}
private class FXCallbackVideoSurface extends CallbackVideoSurface {
FXCallbackVideoSurface() {
super(new FXBufferFormatCallback(), new FXRenderCallback(), true,
VideoSurfaceAdapters.getVideoSurfaceAdapter());
}
}
private class FXBufferFormatCallback implements BufferFormatCallback {
private int sourceWidth;
private int sourceHeight;
@Override
public BufferFormat getBufferFormat(int sourceWidth, int sourceHeight) {
this.sourceWidth = sourceWidth;
this.sourceHeight = sourceHeight;
return new RV32BufferFormat(sourceWidth, sourceHeight);
}
@Override
public void allocatedBuffers(ByteBuffer[] buffers) {
assert buffers[0].capacity() == sourceWidth * sourceHeight * 4;
PixelFormat<ByteBuffer> pixelFormat = PixelFormat.getByteBgraPreInstance();
videoPixelBuffer = new PixelBuffer<>(sourceWidth, sourceHeight, buffers[0], pixelFormat);
videoImage = new WritableImage(videoPixelBuffer);
videoImageView.setImage(videoImage);
}
}
private class FXRenderCallback implements RenderCallback {
@Override
public void display(uk.co.caprica.vlcj.player.base.MediaPlayer mediaPlayer, ByteBuffer[] nativeBuffers,
BufferFormat bufferFormat) {
Platform.runLater(() -> {
videoPixelBuffer.updateBuffer(pb -> null);
});
}
}
}

3
src/main/resources/fxml/PlayerWindow.fxml

@ -16,6 +16,7 @@
<HBox alignment="CENTER" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
<children>
<MediaView fx:id="mediaView" />
<ImageView fx:id="videoImageView" pickOnBounds="true" preserveRatio="true" />
</children>
</HBox>
<VBox fx:id="bottomVBox" alignment="CENTER" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0">
@ -39,7 +40,7 @@
<graphic>
<ImageView fx:id="playIcon" fitHeight="29.0" pickOnBounds="true" preserveRatio="true">
<image>
<Image url="@../icons/baseline_play_arrow_black_48dp.png" />
<Image url="@../icons/baseline_pause_black_48dp.png" />
</image>
</ImageView>
</graphic></JFXButton>

Loading…
Cancel
Save

Du besuchst diese Seite mit einem veralteten IPv4-Internetzugang. Möglicherweise treten in Zukunft Probleme mit der Erreichbarkeit und Performance auf. Bitte frage deinen Internetanbieter oder Netzwerkadministrator nach IPv6-Unterstützung.
You are visiting this site with an outdated IPv4 internet access. You may experience problems with accessibility and performance in the future. Please ask your ISP or network administrator for IPv6 support.
Weitere Infos | More Information
Klicke zum schließen | Click to close