Skip to content

Instantly share code, notes, and snippets.

@jayfella
Last active October 10, 2021 08:19
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save jayfella/8a0dc65354b358c9e5f632a047d0686b to your computer and use it in GitHub Desktop.
Save jayfella/8a0dc65354b358c9e5f632a047d0686b to your computer and use it in GitHub Desktop.
Playing videos in jMonkeyEngine using VLC4J4
// compile group: 'uk.co.caprica', name: 'vlcj', version: '4.1.0'
package com.jayfella.test;
import com.jme3.app.SimpleApplication;
import com.jme3.material.Material;
import com.jme3.material.Materials;
import com.jme3.material.RenderState;
import com.jme3.math.FastMath;
import com.jme3.scene.Geometry;
import com.jme3.scene.shape.Quad;
import com.jme3.system.AppSettings;
import com.jme3.texture.Image;
import com.jme3.texture.Texture2D;
import com.jme3.util.BufferUtils;
import uk.co.caprica.vlcj.factory.MediaPlayerFactory;
import uk.co.caprica.vlcj.player.base.MediaPlayer;
import uk.co.caprica.vlcj.player.embedded.EmbeddedMediaPlayer;
import uk.co.caprica.vlcj.player.embedded.videosurface.callback.BufferFormat;
import uk.co.caprica.vlcj.player.embedded.videosurface.callback.BufferFormatCallback;
import uk.co.caprica.vlcj.player.embedded.videosurface.callback.RenderCallbackAdapter;
import uk.co.caprica.vlcj.player.embedded.videosurface.callback.format.RV32BufferFormat;
import java.nio.ByteBuffer;
public class TestVlcPlayer4 extends SimpleApplication {
public static void main(String... args) {
TestVlcPlayer4 testVlcPlayer4 = new TestVlcPlayer4();
AppSettings appSettings = new AppSettings(true);
appSettings.setResolution(1280, 720);
//appSettings.setFrameRate(120);
appSettings.setTitle("Test :: VLC4J");
appSettings.setUseJoysticks(true);
testVlcPlayer4.setSettings(appSettings);
testVlcPlayer4.setShowSettings(false);
testVlcPlayer4.setPauseOnLostFocus(false);
testVlcPlayer4.start();
}
// private final BufferedImage image;
private MediaPlayerFactory factory;
private EmbeddedMediaPlayer mediaPlayer;
private String media = "M:\\Antz (1998).mkv";
private int width = 720;
private int height = 400;
@Override
public void simpleInitApp() {
flyCam.setMoveSpeed(100);
Image image = new Image();
image.setWidth(width);
image.setHeight(height);
image.setFormat(Image.Format.BGRA8);
image.setData(BufferUtils.createByteBuffer(image.getWidth() * image.getHeight() * 4));
Texture2D jmeTexture = new Texture2D(image);
factory = new MediaPlayerFactory();
mediaPlayer = factory.mediaPlayers().newEmbeddedMediaPlayer();
mediaPlayer.videoSurface().set(factory.videoSurfaces().newVideoSurface(
new TestBufferFormatCallback(),
new JmeRenderCallbackAdapter(jmeTexture),
false));
mediaPlayer.media().play(media);
Geometry screenGeom = new Geometry("Video Screen", new Quad(width, height));
screenGeom.setMaterial(new Material(assetManager, Materials.UNSHADED));
screenGeom.getMaterial().setTexture("ColorMap", jmeTexture);
rootNode.attachChild(screenGeom);
// a little hack to prevent flipping Y.
screenGeom.rotate(0, FastMath.PI, FastMath.PI);
screenGeom.getMaterial().getAdditionalRenderState().setFaceCullMode(RenderState.FaceCullMode.Front);
screenGeom.move(-image.getWidth() * 0.5f, image.getHeight() * 0.5f, 0);
}
private final class TestBufferFormatCallback implements BufferFormatCallback {
@Override
public BufferFormat getBufferFormat(int sourceWidth, int sourceHeight) {
return new RV32BufferFormat(width, height);
}
}
public class JmeRenderCallbackAdapter extends RenderCallbackAdapter {
private ByteBuffer imageBuffer;
private Texture2D texture;
int width;
int height;
public JmeRenderCallbackAdapter(Texture2D texture) {
super(new int[texture.getImage().getWidth() * texture.getImage().getHeight()]);
width = texture.getImage().getWidth();
height = texture.getImage().getHeight();
imageBuffer = BufferUtils.clone(texture.getImage().getData(0));
this.texture = texture;
}
@Override
protected void onDisplay(MediaPlayer mediaPlayer, int[] rgbBuffer) {
// Simply copy buffer to the image and repaint
if(imageBuffer != null){
imageBuffer.rewind();
imageBuffer.clear();
for(int i : rgbBuffer){
imageBuffer.putInt(i);
}
texture.getImage().setData(BufferUtils.clone(imageBuffer));
texture.getImage().setUpdateNeeded();
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment