A couple of months ago i tryed to showcase LWJGL with a video playback feature, it happens that that project died but i wrote some code that is of no value for me now, but could be usefull for anyone who wants some video playback on their apps.
The video playback is based on ffmpeg but the API i wrote in java is quite more simple. You can get all the sources (C++ and Java) and a binary release (win32 only) but it should compile OK under linux and maybe OSX from here:
http://www.scratchydreams.com/projects/lwjgl-mm.7zFeel free to include the code into lwjgl if you like, it is my small donation

To play a movie in a spinning cube all you need to code is:
package org.lwjgl.mm;
import org.lwjgl.opengl.Display;
import org.lwjgl.opengl.DisplayMode;
import org.lwjgl.opengl.GL11;
import org.lwjgl.opengl.glu.GLU;
import org.lwjgl.input.Keyboard;
import org.lwjgl.Sys;
public class AVDecoderTest {
private boolean done = false;
private final String windowTitle = "MM test";
private DisplayMode displayMode;
private AVDecoder mm = new AVDecoder("C:\\msys\\devel\\lwjgl-mm\\test\\test-avi.avi");
private long pts;
private float xrot; // X Rotation ( NEW )
private float yrot; // Y Rotation ( NEW )
private float zrot; // Z Rotation ( NEW )
private int video; // Storage For One Texture ( NEW )
public static void main(String args[]) {
(new AVDecoderTest()).run();
}
public void run() {
try {
init();
while (!done) {
mainloop();
render();
Display.update();
}
cleanup();
}
catch (Exception e) {
e.printStackTrace();
System.exit(0);
}
}
private void mainloop() {
if(Keyboard.isKeyDown(Keyboard.KEY_ESCAPE)) { // Exit if Escape is pressed
done = true;
}
if(Display.isCloseRequested()) { // Exit if window is closed
done = true;
}
}
private boolean render() {
// get the next frame
if(pts <= Sys.getTime()) {
if(!AVDecoder.isError(mm.nextFrame())) {
pts = Sys.getTime() + mm.update();
}
}
GL11.glClear(GL11.GL_COLOR_BUFFER_BIT | GL11.GL_DEPTH_BUFFER_BIT); // Clear The Screen And The Depth Buffer
GL11.glLoadIdentity(); // Reset The Current Modelview Matrix
GL11.glTranslatef(0.0f, 0.0f, -5.0f); // Move Into The Screen 5 Units
GL11.glRotatef(xrot, 1.0f, 0.0f, 0.0f); // Rotate On The X Axis
GL11.glRotatef(yrot, 0.0f, 1.0f, 0.0f); // Rotate On The Y Axis
GL11.glRotatef(zrot, 0.0f, 0.0f, 1.0f); // Rotate On The Z Axis
GL11.glBindTexture(GL11.GL_TEXTURE_2D, video); // Select Our Video frame texture
GL11.glBegin(GL11.GL_QUADS);
// Front Face
GL11.glTexCoord2f(0.0f, 0.0f);
GL11.glVertex3f(-1.0f, -1.0f, 1.0f); // Bottom Left Of The Texture and Quad
GL11.glTexCoord2f(1.0f, 0.0f);
GL11.glVertex3f(1.0f, -1.0f, 1.0f); // Bottom Right Of The Texture and Quad
GL11.glTexCoord2f(1.0f, 1.0f);
GL11.glVertex3f(1.0f, 1.0f, 1.0f); // Top Right Of The Texture and Quad
GL11.glTexCoord2f(0.0f, 1.0f);
GL11.glVertex3f(-1.0f, 1.0f, 1.0f); // Top Left Of The Texture and Quad
// Back Face
GL11.glTexCoord2f(1.0f, 0.0f);
GL11.glVertex3f(-1.0f, -1.0f, -1.0f); // Bottom Right Of The Texture and Quad
GL11.glTexCoord2f(1.0f, 1.0f);
GL11.glVertex3f(-1.0f, 1.0f, -1.0f); // Top Right Of The Texture and Quad
GL11.glTexCoord2f(0.0f, 1.0f);
GL11.glVertex3f(1.0f, 1.0f, -1.0f); // Top Left Of The Texture and Quad
GL11.glTexCoord2f(0.0f, 0.0f);
GL11.glVertex3f(1.0f, -1.0f, -1.0f); // Bottom Left Of The Texture and Quad
// Top Face
GL11.glTexCoord2f(0.0f, 1.0f);
GL11.glVertex3f(-1.0f, 1.0f, -1.0f); // Top Left Of The Texture and Quad
GL11.glTexCoord2f(0.0f, 0.0f);
GL11.glVertex3f(-1.0f, 1.0f, 1.0f); // Bottom Left Of The Texture and Quad
GL11.glTexCoord2f(1.0f, 0.0f);
GL11.glVertex3f(1.0f, 1.0f, 1.0f); // Bottom Right Of The Texture and Quad
GL11.glTexCoord2f(1.0f, 1.0f);
GL11.glVertex3f(1.0f, 1.0f, -1.0f); // Top Right Of The Texture and Quad
// Bottom Face
GL11.glTexCoord2f(1.0f, 1.0f);
GL11.glVertex3f(-1.0f, -1.0f, -1.0f); // Top Right Of The Texture and Quad
GL11.glTexCoord2f(0.0f, 1.0f);
GL11.glVertex3f(1.0f, -1.0f, -1.0f); // Top Left Of The Texture and Quad
GL11.glTexCoord2f(0.0f, 0.0f);
GL11.glVertex3f(1.0f, -1.0f, 1.0f); // Bottom Left Of The Texture and Quad
GL11.glTexCoord2f(1.0f, 0.0f);
GL11.glVertex3f(-1.0f, -1.0f, 1.0f); // Bottom Right Of The Texture and Quad
// Right face
GL11.glTexCoord2f(1.0f, 0.0f);
GL11.glVertex3f(1.0f, -1.0f, -1.0f); // Bottom Right Of The Texture and Quad
GL11.glTexCoord2f(1.0f, 1.0f);
GL11.glVertex3f(1.0f, 1.0f, -1.0f); // Top Right Of The Texture and Quad
GL11.glTexCoord2f(0.0f, 1.0f);
GL11.glVertex3f(1.0f, 1.0f, 1.0f); // Top Left Of The Texture and Quad
GL11.glTexCoord2f(0.0f, 0.0f);
GL11.glVertex3f(1.0f, -1.0f, 1.0f); // Bottom Left Of The Texture and Quad
// Left Face
GL11.glTexCoord2f(0.0f, 0.0f);
GL11.glVertex3f(-1.0f, -1.0f, -1.0f); // Bottom Left Of The Texture and Quad
GL11.glTexCoord2f(1.0f, 0.0f);
GL11.glVertex3f(-1.0f, -1.0f, 1.0f); // Bottom Right Of The Texture and Quad
GL11.glTexCoord2f(1.0f, 1.0f);
GL11.glVertex3f(-1.0f, 1.0f, 1.0f); // Top Right Of The Texture and Quad
GL11.glTexCoord2f(0.0f, 1.0f);
GL11.glVertex3f(-1.0f, 1.0f, -1.0f); // Top Left Of The Texture and Quad
GL11.glEnd();
// xrot += 0.3f; // X Axis Rotation
// yrot += 0.2f; // Y Axis Rotation
// zrot += 0.4f; // Z Axis Rotation
return true;
}
private void createWindow() throws Exception {
Display.setFullscreen(false);
DisplayMode d[] = Display.getAvailableDisplayModes();
for (DisplayMode aD : d) {
if (aD.getWidth() == 640
&& aD.getHeight() == 480
&& aD.getBitsPerPixel() == 32) {
displayMode = aD;
break;
}
}
Display.setDisplayMode(displayMode);
Display.setTitle(windowTitle);
Display.create();
}
private void init() throws Exception {
createWindow();
initGL();
if(!AVDecoder.isError(mm.open()))
video = mm.createGLVideoTexture();
}
private void initGL() {
GL11.glEnable(GL11.GL_TEXTURE_2D); // Enable Texture Mapping
GL11.glShadeModel(GL11.GL_SMOOTH); // Enable Smooth Shading
GL11.glClearColor(0.0f, 0.0f, 0.0f, 0.0f); // Black Background
GL11.glClearDepth(1.0f); // Depth Buffer Setup
GL11.glEnable(GL11.GL_DEPTH_TEST); // Enables Depth Testing
GL11.glDepthFunc(GL11.GL_LEQUAL); // The Type Of Depth Testing To Do
GL11.glMatrixMode(GL11.GL_PROJECTION); // Select The Projection Matrix
GL11.glLoadIdentity(); // Reset The Projection Matrix
// Calculate The Aspect Ratio Of The Window
GLU.gluPerspective(45.0f, (float) displayMode.getWidth() / (float) displayMode.getHeight(), 0.1f, 100.0f);
GL11.glMatrixMode(GL11.GL_MODELVIEW); // Select The Modelview Matrix
// Really Nice Perspective Calculations
GL11.glHint(GL11.GL_PERSPECTIVE_CORRECTION_HINT, GL11.GL_NICEST);
}
private void cleanup() {
Display.destroy();
mm.close();
}
}
To summarise:
You open a stream:
private AVDecoder mm = new AVDecoder("C:\\msys\\devel\\lwjgl-mm\\test\\test-avi.avi");
and then you render:
// get the next frame
if(pts <= Sys.getTime()) {
if(!AVDecoder.isError(mm.nextFrame())) {
pts = Sys.getTime() + mm.update();
}
}