最近几天,我一直在尝试使用java vlcj库播放多个4k视频,彼此之间没有黑色(缓冲?)帧。
我的想法是,将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调试消息。仅当我关闭应用程序时。但这可能是因为我没有正确进行垃圾收集。
感谢您提供的任何帮助。
亲切的问候