javavlccodecwindows-11vlcj

videoplayer.stop() causes JVM crash under Windows 11 (certain video codecs only)


After migrating my Java vlcj application to my new Windows 11 machine, the program crashes on calling vlcjplayer.stop(). I am using vlcj 4.8.2 in combination with VLC 3.0.21. I am shipping my own Oracle JRE, the version is 17.0.12.

This is the relevant part of the code I am calling (where stop() is being called from a button ActionListener and vlcPlayer is of the type EmbeddedMediaPlayer):

public void stop() {
    submit(() -> vlcPlayer.stop());// new since vlcj-4: callback to VLC from a separate thread!
}

public void submit (final Runnable runnable) {
    vlcPlayer.submit(runnable);
}

Some side facts:

  1. The exact same code is running fine on Windows 10! Same Java version, same VLC version, same version of vlcj, same build!
  2. The problem only occurs for certain videos encodings: mp4, mkv, ..., whereas older mpeg2 videos do not cause the issue!
  3. When I play the problematic videos using the official vlcj test application, the crashes do not occur! I compared the respective code sections, but could not find a real difference in the way the stop method is being invoked
  4. The issue seems not to be connected to my specific personal system setup. It occurs on any Windows 11 machine I have run my application on so far

The VLC logfile does not contain any errors. The process just crashes while logs are being written to it. I was searching the Windows event viewer for errors and I could find the respective error events. Here is how they look like (it's in German unfortunately):

Fehlerhafter Anwendungsname: java.exe, Version: 17.0.12.0, Zeitstempel: 0x31da67d3
Fehlerhafter Modulname: libdirect3d11_filters_plugin.dll, Version: 3.0.21.0, Zeitstempel: 0x0075006c
Ausnahmecode: 0xc0000005
Fehleroffset: 0x000000000000155a
Fehlerhafte Prozess-ID: 0x1E5C
Fehlerhafte Anwendungsstartzeit: 0x1DB641EF886AD0F
Fehlerhafter Anwendungspfad: D:\Java_Programme\Jukebox\jre-17.0.12\bin\java.exe
Fehlerhafter Modulpfad: C:\Program Files\VideoLAN\VLC\plugins\d3d11\libdirect3d11_filters_plugin.dll
Berichts-ID: a6019a38-7882-422c-bafa-2b1fa2bd6f7c
Vollständiger Name des fehlerhaften Pakets: 
Fehlerhafte paketbezogene Anwendungs-ID: 

I have tried various things like setting the video output to opengl instead of direct3d11, and I have also changed the respective settings in native VLC, but with no effect. Somehow I cannot get my player to use another video output module. On the other hand, I would not want to force users to make manual changes to these kind of settings anyways. I am not into video codecs, the whole native library stuff and the depths of VLC at all. I have been struggling with this for a couple of days now and don't see what could be wrong.

If the issue is with my Java code, then why does it run on my old Windows 10 machine and with older codecs? If the issue is with VLC and the installed codecs, then why does the crash not happen when I run the vlcj test application? I have installed the latest GPU drivers and I have a clean and fresh Windows 11 installation.

I managed to capture a screenshot of an error message VLC logs to the console. (1) is where I call vlcplayer.stop(), (2) is when the vlcj event handler receives the stopped() event. In between the native VLC throws an error (that leads to the crash, obviously):

enter image description here

Working code example:

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JButton;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.border.EtchedBorder;

import uk.co.caprica.vlcj.filefilters.swing.SwingFileFilterFactory;
import uk.co.caprica.vlcj.player.component.EmbeddedMediaPlayerComponent;

/**
 * @author Oender
 */
public class VLCJTest extends JFrame {

    private static final long serialVersionUID = 1L;
    private EmbeddedMediaPlayerComponent playerComponent;
    
    /**
     * Constructor
     */
    public VLCJTest() {

        super.setTitle("VLCJ Test (fixed)");
        super.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        playerComponent = new EmbeddedMediaPlayerComponent();
        initComponents();
    }


    /**
     * Initialize & arrange components
     */
    private void initComponents() {

        final JPanel content = new JPanel (new BorderLayout());
        content.setPreferredSize (new Dimension(400,300));
        
        final JPanel buttonPanel = new JPanel();
        buttonPanel.setBorder(new EtchedBorder());
        
        final JButton openButton = new JButton("Open");
        openButton.setFocusable(false);

        final JButton stopButton = new JButton("Stop Video");
        stopButton.setFocusable(false);

        // attach ActionListener
        openButton.setActionCommand("Open");
        openButton.addActionListener(new ActionListener() { 
            public void actionPerformed (ActionEvent e) {
                final JFileChooser chooser = new JFileChooser();
                chooser.setFileFilter(SwingFileFilterFactory.newMediaFileFilter());
                final int state = chooser.showOpenDialog(null);
                if (state == JFileChooser.APPROVE_OPTION) {
                    playerComponent.mediaPlayer().media().play(chooser.getSelectedFile().getPath());
                }
            }
        });

        // attach ActionListener
        stopButton.setActionCommand("Stop");
        stopButton.addActionListener(new ActionListener() {
            public void actionPerformed (ActionEvent e) {
                playerComponent.mediaPlayer().controls().stop();
            }
        });
        
        buttonPanel.add(openButton);
        buttonPanel.add(stopButton);
        
        content.add(buttonPanel, BorderLayout.NORTH);
        content.add(playerComponent, BorderLayout.CENTER);
        
        super.setContentPane(content);
        super.pack();
        super.setVisible(true);
    }

    /**
     * @param args
     */
    public static void main (String[] args) {
        new VLCJTest().setVisible(true);
    }
}

Code example that causes the crash:

```java
import java.awt.BorderLayout;
import java.awt.Canvas;
import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JButton;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.border.EtchedBorder;

import com.sun.jna.NativeLibrary;

import uk.co.caprica.vlcj.factory.MediaPlayerFactory;
import uk.co.caprica.vlcj.filefilters.swing.SwingFileFilterFactory;

import uk.co.caprica.vlcj.player.embedded.EmbeddedMediaPlayer;
import uk.co.caprica.vlcj.player.embedded.videosurface.ComponentVideoSurface;

/**
 * @author Oender
 */
public class VLCJTest extends JFrame {

    private static final long serialVersionUID = 1L;
    private EmbeddedMediaPlayer player;
    
    /**
     * Constructor
     */
    public VLCJTest() {

        super.setTitle("VLCJ Test (crash)");
        super.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        final Canvas videoCanvas = new Canvas();

        player = initPlayer(videoCanvas);
        initComponents(videoCanvas);
    }
    

    /**
     * Initialize & arrange components
     * @param videoCanvas
     */
    private void initComponents (final Canvas videoCanvas) {

        final JPanel content = new JPanel (new BorderLayout());
        content.setPreferredSize (new Dimension(400,300));
        
        final JPanel buttonPanel = new JPanel();
        buttonPanel.setBorder(new EtchedBorder());
        
        final JButton openButton = new JButton("Open");
        openButton.setFocusable(false);

        final JButton stopButton = new JButton("Stop Video");
        stopButton.setFocusable(false);

        // attach ActionListener
        openButton.setActionCommand("Open");
        openButton.addActionListener(new ActionListener() { 
            public void actionPerformed (ActionEvent e) {
                final JFileChooser chooser = new JFileChooser();
                chooser.setFileFilter(SwingFileFilterFactory.newMediaFileFilter());
                final int state = chooser.showOpenDialog(null);
                if (state == JFileChooser.APPROVE_OPTION) {
                    player.media().play(chooser.getSelectedFile().getPath());
                }
            }
        });

        // attach ActionListener
        stopButton.setActionCommand("Stop");
        stopButton.addActionListener(new ActionListener() {
            public void actionPerformed (ActionEvent e) {
                player.controls().stop();
            }
        });
        
        buttonPanel.add(openButton);
        buttonPanel.add(stopButton);

        content.add(buttonPanel, BorderLayout.NORTH);
        content.add(videoCanvas, BorderLayout.CENTER);
        
        super.setContentPane(content);
        super.pack();
        super.setVisible(true);
    }

    /**
     * create the EmbeddedMediaPlayer
     * @param canvas
     * @return
     */
    private EmbeddedMediaPlayer initPlayer (final Canvas canvas) {

        final MediaPlayerFactory factory = new MediaPlayerFactory();
        final ComponentVideoSurface videoSurface = factory.videoSurfaces().newVideoSurface(canvas);

        final EmbeddedMediaPlayer mPlayer = factory.mediaPlayers().newEmbeddedMediaPlayer();
        mPlayer.videoSurface().set(videoSurface);
        mPlayer.video().setAdjustVideo(true);
        return mPlayer;
    }

    /**
     * @param args
     */
    public static void main (String[] args) {
        
        NativeLibrary.addSearchPath("libvlc", "C:\\Program Files\\VideoLAN\\VLC");
        new VLCJTest().setVisible(true);
    }
}

Solution

  • This is not a problem in vlcj.

    See https://code.videolan.org/videolan/vlc/-/issues/29069 for the issue in VLC.

    This seems to be resolved in the latest VLC 3.x nightly build here https://artifacts.videolan.org/vlc-3.0/nightly-win64/20250307-0220/, which will hopefully soon result in a VLC 3.0.22 release containing the fix.