Caprica Software

vlcj 4.x Tutorial

Java IO

It is possible to play media using standard Java IO.

There are however some limitations, and in some cases they may be critical limitations.

The vast majority of applications will not need to use this feature and can instead rely on the native media playback via a Media Resource Locator (MRL) as has always been the case with vlcj.


How it Works

LibVLC 3.0.0 added new native "media callbacks" which are used to open, read, seek and close a media "stream". Essentially this enables VLC to callback into a Java application to open the media, read a sequence of bytes from the media data to populate a native IO buffer, seek to any position within the media data, and when done to close the media.

The key step is to populate a supplied native IO buffer with media data on demand.

vlcj provides CallbackMedia classes that help you use Java IO to play your media.


Seekability

The first consideration is that of "seekability" - is it possible, using Java IO, to seek to any position within the media?

The natural choice for seekability is to use a RandomAccessFile, where by definition it is possible to seek to any position within such a file before reading the data.

With vlcj 5.0.0, the callback media using a RandomAccessFile has been removed and is superseded by an implementation that uses a MappedByteBuffer.

Just about every Java InputStream is not seekable - rather the data is consumed from the stream in a linear manner from start to finish. Some InputStream implementations allow to seek forwards by skipping bytes, but seeking backwards within a stream is rarely possible. It is possible to create a bespoke implementation of an InputStream that allows seeking, but this may not be straightforward, and in the simplest case it would require that the entire media data be held in an in-memory buffer.

Seekability is therefore a factor that you must consider - some media types simply can not be played without the ability to seek.


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.

We start by assuming we already have a media player component:

mediaPlayerComponent = new EmbeddedMediaPlayerComponent();

Rather than play an MRL as is the norm with vlcj, we play a Media instance...


Create a Media Instance

For seekable media, we use the vlcj RandomAccessFileMedia class, and pass it when invoke playMedia on the media player:

CallbackMedia media = new RandomAccessFileMedia(new File("MyCoolMovie.mp4"));
mediaPlayerComponent.mediaPlayer().media().play(media);

For non-seekable media, in this case we want to use a FileInputStream and the vlcj FileInputStreamMedia class:

CallbackMedia media = new FileInputStreamMedia(new File("MyCoolMusic.mp3"));
mediaPlayerComponent.mediaPlayer().media().play(media);

Media Options

You can pass media options when you create your CallbackMedia instance.

These are the same media options that are ordinarily passed when you invoke play on the media player instance. All of the concrete vlcj CallbackMedia implementation classes accept zero or more media options via their constructors.

String[] mediaOptions = {...};
CallbackMedia media = new RandomAccessFileMedia(new File("MyCoolMovie.mp4"), mediaOptions);
mediaPlayerComponent.mediaPlayer().media().play(media);

Custom Media Types

vlcj provides scaffolding and implementations for the most common use-cases, but if you need to it is possible to extend the vlcj classes to implement your own bespoke behaviour.


Summary

You can play media with vlcj using standard Java IO - however, there are constraints particularly with regard to the non-seekability of the standard Java input streams.