new media player based on vlcj [Part 1]
continuous-integration/drone/push Build is passing Details

* openjfx 12.0.2 -> 14
* log4j 2.13.0 -> 2.13.1
* maven-shade-plugin 3.2.1 -> 3.2.2
This commit is contained in:
Jannik 2020-04-01 19:48:44 +02:00
parent ef5d87c54c
commit 4184e982ea
Signed by: Seil0
GPG Key ID: E8459F3723C52C24
7 changed files with 460 additions and 75 deletions

18
pom.xml
View File

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

View File

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

View File

@ -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
}
}

View File

@ -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);
});
}
}
}

View File

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

View File

@ -1,7 +1,7 @@
/** /**
* Project-HomeFlix * Project-HomeFlix
* *
* Copyright 2016-2019 <@Seil0> * Copyright 2016-2020 <seil0@mosad.xyz>
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@ -22,15 +22,14 @@
package kellerkinder.HomeFlix.player; package kellerkinder.HomeFlix.player;
import java.io.File; import java.nio.ByteBuffer;
import java.util.Timer; import java.util.Timer;
import java.util.TimerTask; import java.util.TimerTask;
import com.jfoenix.controls.JFXButton; import com.jfoenix.controls.JFXButton;
import com.jfoenix.controls.JFXSlider; import com.jfoenix.controls.JFXSlider;
import javafx.beans.binding.Bindings; import javafx.application.Platform;
import javafx.beans.property.DoubleProperty;
import javafx.beans.value.ChangeListener; import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue; import javafx.beans.value.ObservableValue;
import javafx.event.ActionEvent; import javafx.event.ActionEvent;
@ -39,21 +38,34 @@ import javafx.fxml.FXML;
import javafx.scene.Cursor; import javafx.scene.Cursor;
import javafx.scene.image.Image; import javafx.scene.image.Image;
import javafx.scene.image.ImageView; 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.input.MouseEvent;
import javafx.scene.layout.HBox; import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox; import javafx.scene.layout.VBox;
import javafx.scene.media.Media; import javafx.scene.media.Media;
import javafx.scene.media.MediaPlayer; import javafx.scene.media.MediaPlayer;
import javafx.scene.media.MediaPlayer.Status;
import javafx.scene.media.MediaView; import javafx.scene.media.MediaView;
import javafx.util.Duration; import javafx.util.Duration;
import kellerkinder.HomeFlix.controller.DBController; import kellerkinder.HomeFlix.controller.DBController;
import kellerkinder.HomeFlix.controller.XMLController; import kellerkinder.HomeFlix.controller.XMLController;
import kellerkinder.HomeFlix.datatypes.FilmTabelDataType; 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 { public class PlayerController {
@FXML private MediaView mediaView; @FXML private MediaView mediaView;
@FXML private ImageView videoImageView;
@FXML private VBox bottomVBox; @FXML private VBox bottomVBox;
@ -72,13 +84,19 @@ public class PlayerController {
private Player player; private Player player;
private Media media; 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 FilmTabelDataType film;
private double currentTime = 0; private long currentTime = 0;
private double seekTime = 0; private long seekTime = 0;
private double startTime = 0; private long startTime = 0;
private double duration = 0; private long duration = 0;
private int season = 0; private int season = 0;
private int episode = 0; private int episode = 0;
private int countdown = 0; private int countdown = 0;
@ -100,7 +118,62 @@ public class PlayerController {
public PlayerController(Player player, String streamURL) { public PlayerController(Player player, String streamURL) {
this.player = player; this.player = player;
this.film = DBController.getInstance().getStream(streamURL); 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 * initialize the PlayerWindow
@ -108,54 +181,27 @@ public class PlayerController {
public void init() { public void init() {
initActions(); 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(); initMediaPlayer();
// set the control elements to the correct value
playIcon.setImage(pause);
fullscreenIcon.setImage(fullscreenExit);
timeSlider.setValue(0);
} }
private void initMediaPlayer() { private void initMediaPlayer() {
// start the media if the player is ready // start the media if the player is ready
mediaPlayer.setOnReady(new Runnable() { mediaPlayer2.setOnReady(new Runnable() {
@Override @Override
public void run() { public void run() {
duration = media.getDuration().toMillis(); duration = (long) media.getDuration().toMillis();
timeSlider.setMax((duration / 1000) / 60); timeSlider.setMax((duration / 1000) / 60);
mediaPlayer.play(); mediaPlayer2.play();
mediaPlayer.seek(Duration.millis(startTime)); mediaPlayer2.seek(Duration.millis(startTime));
} }
}); });
// every time the play time changes execute this // every time the play time changes execute this
mediaPlayer.currentTimeProperty().addListener(new ChangeListener<Duration>() { mediaPlayer2.currentTimeProperty().addListener(new ChangeListener<Duration>() {
@Override @Override
public void changed(ObservableValue<? extends Duration> observable, Duration oldValue, Duration newValue) { 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); double timeToEnd = (duration - currentTime);
if (timeToEnd < 20000 && episode != 0 && autoplay) { if (timeToEnd < 20000 && episode != 0 && autoplay) {
@ -176,7 +222,7 @@ public class PlayerController {
} }
} else if (timeToEnd < 120) { } else if (timeToEnd < 120) {
// if we are 120ms to the end stop the media // 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 DBController.getInstance().setCurrentTime(film.getStreamUrl(), 0); // reset old video start time
playIcon.setImage(playArrow); playIcon.setImage(playArrow);
} else { } else {
@ -232,7 +278,7 @@ public class PlayerController {
timeSlider.setOnMouseReleased(new EventHandler<MouseEvent>() { timeSlider.setOnMouseReleased(new EventHandler<MouseEvent>() {
@Override @Override
public void handle(MouseEvent event) { public void handle(MouseEvent event) {
mediaPlayer.seek(new Duration(seekTime)); mediaPlayer2.seek(new Duration(seekTime));
mousePressed = false; mousePressed = false;
} }
}); });
@ -248,15 +294,14 @@ public class PlayerController {
timeSlider.valueProperty().addListener(new ChangeListener<Number>() { timeSlider.valueProperty().addListener(new ChangeListener<Number>() {
@Override @Override
public void changed(ObservableValue<? extends Number> ov, Number old_val, Number new_val) { 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 @FXML
void stopBtnAction(ActionEvent event) { void stopBtnAction(ActionEvent event) {
DBController.getInstance().setCurrentTime(film.getStreamUrl(), currentTime); stop2();
mediaPlayer.stop();
player.getStage().close(); player.getStage().close();
} }
@ -273,11 +318,11 @@ public class PlayerController {
@FXML @FXML
void playBtnAction(ActionEvent event) { void playBtnAction(ActionEvent event) {
if (mediaPlayer.getStatus().equals(Status.PLAYING)) { if (embeddedMediaPlayer.status().isPlaying()) {
mediaPlayer.pause(); embeddedMediaPlayer.controls().pause();
playIcon.setImage(playArrow); playIcon.setImage(playArrow);
} else { } else {
mediaPlayer.play(); embeddedMediaPlayer.controls().play();
playIcon.setImage(pause); playIcon.setImage(pause);
} }
} }
@ -292,7 +337,7 @@ public class PlayerController {
DBController.getInstance().setCurrentTime(film.getStreamUrl(), 0); // reset old video start time DBController.getInstance().setCurrentTime(film.getStreamUrl(), 0); // reset old video start time
FilmTabelDataType nextFilm = DBController.getInstance().getNextEpisode(film.getTitle(), episode, season); FilmTabelDataType nextFilm = DBController.getInstance().getNextEpisode(film.getTitle(), episode, season);
if (nextFilm != null) { if (nextFilm != null) {
mediaPlayer.stop(); mediaPlayer2.stop();
film = nextFilm; film = nextFilm;
init(); init();
autoplay = true; autoplay = true;
@ -300,11 +345,52 @@ public class PlayerController {
} }
public MediaPlayer getMediaPlayer() { public MediaPlayer getMediaPlayer() {
return mediaPlayer; return mediaPlayer2;
} }
public double getCurrentTime() { public double getCurrentTime() {
return currentTime; 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);
});
}
}
} }

View File

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