Последние несколько дней я пытался воспроизвести несколько видео 4k с библиотекой java vlcj, друг за другом без черных (буферных?) Кадров между ними.
Моя идея заключалась в том, что япоместите JLabel поверх холста для EmbeddedVideoPlayer.Когда я нажимаю кнопку для следующего видео, я приостанавливаю текущее видео -> сделать изображение кадра в этот момент -> нарисовать это изображение на JLabel -> сделать JLabel видимым.Когда действительно начнется следующее видео, я сделаю JLabel снова невидимым.В идеале пользователю никогда не придется смотреть на черные рамки.
public class FullscreenPlayer {
public final EmbeddedMediaPlayerComponent mediaPlayerComponent;
public final EmbeddedMediaPlayer mediaPlayer;
public JFrame frame;
public JLabel overlayLabel;
boolean posChanged = false;
String fhdVideoPath;
public FullscreenPlayer(int screen) {
System.setProperty("sun.awt.noerasebackground", "true");
GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
GraphicsDevice[] gs = ge.getScreenDevices();
Rectangle bounds = gs[screen].getDefaultConfiguration().getBounds();
final String[] VLC_ARGS = { "--intf", "dummy", /* no interface */
/*"--vout", "dummy", we don't want video (output) */
"--no-audio", /* we don't want audio (decoding) */
"--no-snapshot-preview", /* no blending in dummy vout */
};
MediaPlayerFactory mediaPlayerFactory = new MediaPlayerFactory(VLC_ARGS);
Canvas videoCanvas = new Canvas();
videoCanvas.setBounds(0, 0, bounds.width, bounds.height);
videoCanvas.setIgnoreRepaint(true);
overlayLabel = new JLabel();
overlayLabel.setBounds(0, 0, bounds.width, bounds.height);
overlayLabel.setBackground(Color.black);
overlayLabel.setVisible(true);
overlayLabel.setIgnoreRepaint(true);
Panel p = new Panel();
p.setLayout(null);
p.setBackground(Color.black);
p.setIgnoreRepaint(true);
p.add(overlayLabel);
p.add(videoCanvas);
frame = new JFrame();
mediaPlayerComponent = new EmbeddedMediaPlayerComponent() {
private static final long serialVersionUID = 1L;
@Override
protected FullScreenStrategy onGetFullScreenStrategy() {
return new Win32FullScreenStrategy(frame);
}
};
// mediaPlayer = mediaPlayerComponent.getMediaPlayer();
mediaPlayer = mediaPlayerFactory.newEmbeddedMediaPlayer();
mediaPlayer.setVideoSurface(mediaPlayerFactory.newVideoSurface(videoCanvas));
mediaPlayer.addMediaPlayerEventListener(new MediaPlayerEventAdapter() {
@Override
public void positionChanged(MediaPlayer mediaPlayer, float newPosition) {
super.positionChanged(mediaPlayer, newPosition);
if (!posChanged) {
System.out.println("Position changed!");
posChanged = true;
overlayLabel.setVisible(false);
}
}
});
// frame.add(videoCanvas);
frame.setLayout(new BorderLayout());
frame.add(p, BorderLayout.CENTER);
frame.setSize(bounds.width, bounds.height);
frame.setLocation(bounds.x, bounds.y);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setBackground(Color.black);
frame.setVisible(true);
frame.setLocationRelativeTo(null);
frame.setIgnoreRepaint(true);
frame.addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
mediaPlayer.release();
mediaPlayerFactory.release();
System.exit(0);
}
});
frame.addKeyListener(new KeyAdapter() {
@Override
public void keyPressed(KeyEvent e) {
switch (e.getKeyChar()) {
case 'q':
overlayLabel.setVisible(!overlayLabel.isVisible());
break;
case 'w':
BufferedImage img = mediaPlayer.getSnapshot();
overlayTest(img);
break;
}
}
});
mediaPlayer.setFullScreenStrategy(new Win32FullScreenStrategy(frame));
mediaPlayer.setFullScreen(true);
}
public void start(String uhdPath, String fhdPath) {
fhdVideoPath = fhdPath;
mediaPlayer.pause();
try {
BufferedImage img = mediaPlayer.getSnapshot();
if (mediaPlayer.getTime() > 0 || mediaPlayer.getTime() != -1) {
overlayTest(img);
}
PresentationStarter.fhdInstance.mediaPlayer.pause();
mediaPlayer.playMedia(uhdPath);
posChanged = false;
} catch (Exception e) {
e.printStackTrace();
}
}
public void overlayTest(BufferedImage image) {
double i_h = image.getHeight(null);
double i_w = image.getWidth(null);
double c_w = frame.getWidth();
int imgHeight = (int) (i_h / (i_w / c_w));
int imgWidth = (int) c_w;
BufferedImage resizedImage = PresentationStarter.resize(image, imgWidth, imgHeight);
ImageIcon imgIcon = new ImageIcon(resizedImage);
overlayLabel.setIcon(imgIcon);
overlayLabel.setVisible(true);
// The repaint happens after this point.
}
}
Я не вижу сообщений отладки vlcj при воспроизведении видео.Только когда я закрываю приложение.Но это может быть потому, что я не собираю мусор должным образом.
Я благодарен за любую помощь.
С уважением