Caprica Software

vlcj 3.x Tutorial

Overlay

Building on previous tutorials, we will now show you how to use the video overlay.


Background Information

Needing to draw graphics or to overlay user interface widgets on top of a video surface is not an unreasonable requirement, but there are some severe constraints that make this a difficult thing to do.

The main constraint is that when a native media player is embedded inside a Java application that media player needs to be told which window to render the video into. It can only do this by being given an operating system window handle. This essentially means that you can only render video into a user interface widget that is backed by a native window.

In a Java application this basically means that you must use a heavyweight AWT component, and for the specific case of embedding a video surface your only real choice is to use an AWT Canvas class.

You can not use any lightweight Swing component - specifically you can not use a JPanel - why? Because Swing components are not backed by native widgets. The native media player knows nothing about Swing and certainly can not access any lightweight components.

This is a real shame because it is pretty easy to do your own graphics rendering in, or to add your own widgets to, a JPanel.

So you just have to deal with the fact that you can't use a JPanel, and consequently that you can't do lightweight painting or add lightweight widgets.


Well, What Can Be Done?

The EmbeddedMediaPlayer provides a reasonable but not ideal solution to help you create a useful overlay.

This overlay works by keeping a second top-level heavyweight window in sync with the media player video surface. This means resizing the overlay window when the video window size changes, and moving the overlay window when the video window is moved. A top level window can be made transparent, you can paint into it using a regular Graphics2D context, and you can add widgets. This gives the illusion of overlaying painting and widgets on top of your video window.

This is not an ideal approach because there is a notable lag when dragging or resizing the video window - when the window size and position event notification is received, the overlay window must then reposition and or resize itself. Due to how the events are delivered the lag is inevitable. In practical terms it means that you while you drag your video window, the overlay remains in its original position until you finish your drag at which point it snaps back to the right position.

On the other hand, this approach works really well when using native full-screen mode.


Let's Get Started

You should now already have a basic template for how to create a vlcj application, so this tutorial will no longer duplicate all of the code each time - instead we'll just show the new code fragments.


Creating the Overlay

An overlay is just a top-level Window. You create a Window, configure it appropriately (importantly for the overlay you give it a transparent background) and attach it to the media player.

public class Overlay extends Window {
public Overlay(Window owner) {
super(owner, WindowUtils.getAlphaCompatibleGraphicsConfiguration());
setBackground(new Color(0, 0, 0, 0));
}
}

This shows the minimal code required to create an overlay.

Note that prior to Java7 you may need to use AWTUtilities.setWindowOpaque(this, false); instead of setting a fully transparent background colour on the window.

So far this overlay implementation does not really do anything useful. We need to add some custom painting. Inside our Overlay class we simply override the paint method.

We'll use some arbitrary Java2D code in the paint method to demonstrate that the transparency is working, and that our painting is alpha-blended correctly on top of the video.

@Override
public void paint(Graphics g) {
super.paint(g);

Graphics2D g2 = (Graphics2D)g;
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);

GradientPaint gp = new GradientPaint(
180.0f, 280.0f,
new Color(255, 255, 255, 255),
250.0f,
380.0f,
new Color(255, 255, 0, 0)
);
g2.setPaint(gp);

for (int i = 0; i < 3; i ++ ) {
g2.drawOval(150, 280, 100, 100);
g2.fillOval(150, 280, 100, 100);
g2.translate(120, 20);
}
}

You could render text here, draw icons, whatever you want using Java2D painting operations. You can use layout managers, add regular Swing widgets - remember that this overlay window is completely independent of the underlying video window.

Note that the overlay constructor accepts an owner parameter - this should always be the window or frame that contains your video surface.

Overlay overlay = new Overlay(mainFrame);

Using the Overlay

First you associate the overlay with the media player.

mediaPlayerComponent.getMediaPlayer().setOverlay(overlay);

Next you show or hide the overlay whenever you want, in response to some event or a user interaction or whatever your application needs.

mediaPlayerComponent.getMediaPlayer().enableOverlay(enable);

Be Careful

When overlaying top-level windows as described in this tutorial, there is a chance that your desktop window manager may apply its own compositing effects and may actually blend your overlay window with the video underneath it. Usually this is not what you want as it may have unintended consequences like inadvertently darkening or lightening the video surface underneath. Therefore you may need to check whether or not you need to disable your compositing window manager if you want to use this overlay.

When you set an overlay, your application is still the 'owner' of the overlay and responsible for its lifecycle - what this means is that you must dispose of the overlay when you no longer need it. If you set an overlay once and never change it then you likely won't have a problem, but if you set a different overlay instance on your media player you must remember to dispose the old one (if you no longer need it) otherwise you will incur resource leaks.


Alternatives

If you only need to paint text or images over the video surface you should consider using the marquee or logo features of the media player - it will be much simpler.

You can also consider using a so-called "direct rendering" media player.

These concepts are explained in other tutorials.