So here's the result of my latest little attempt to render video to a jME texture. Code can be found here:
http://www.tijl.demon.nl/jme/JFjr/----------------------------
Setup:
I'm afraid the setup is still a bit complicated, but at least it's not as bad as before. I'm assuming Eclipse is used, however, it should be possible to do with other IDEs too.
(edit: 15-05-2007, check out this post by user unixseb on how to initialize FOBS without ever even opening JMF!
http://www.jmonkeyengine.com/jmeforum/index.php?topic=2908.msg40418#msg40418)
----------------------------
First, make a project, and import the source code from the zip into it. There are several ways you can use this code. I recommend 4, as it has excellent performance, and doesn't do any allocations (except for the initial buffer of course) unlike the other methods, which prevents garbage collection.
Sun downloads:
http://java.sun.com/products/java-media/jmf/FOBS download here:
http://sourceforge.net/project/showfiles.php?group_id=105646(NOTE: for a binary build, choose FOBS4JMF. For source, look in FOBS-src)
1. Sun's build of JMF. You'll have support for a few file formats, which on linux/windows can be "accelerated". Most noteable support is for MPEG and AVI/XVID. Most noteable lack is MP3 in AVI. If you're on a Mac I would not recommend this option.
Tip for windows users: There is no need to keep the options to copy dll files to windows/system on, because we can specify their library.path ourself. (in /system they did not work on my machine)
---
2. FOBS build of JMF. Practically every format for audio and video will be supported, on mac/linux/windows. However, native files for accelerated sound output (such as DirectSound) are not included. And since JavaSound is broken more often than not with me, if you want audio, that's recommended. You'll have to copy the native files from the Sun build to the FOBS build directory, if you want accelerated sound. (or follow explanation on the FOBS page)
---
3. Manual installation of FOBS into existing Sun JMF. basically a combination of both, will always give you proper sound support. Might also be useful to those who want sound and can't figure out how to get 2 with working sound.
instructions here:
http://fobs.sourceforge.net/f4jmf_first.html---
4. FOBS with my FOBS patch. Doing this patch for FOBS is actually quite
easy, considering most steps have to be done anyway. You'll need to do the same as either 3 or 2, but also download the java part of the source of FOBS (it's in the \fobs-src\src\jmf-pi\ dir in the archive). Put it in your project. Some errors will show up, related to not having JOGL. Either ignore the error or delete these files.
Now for the patch:
In
com.omnividea.media.parser.video.VideoTrack
there is a method
public void readFrame(Buffer buffer)
now replace the if block:
if(FobsConfiguration.useNativeBuffers) {
...
}
with:
if(FobsConfiguration.useNativeBuffers)
{
if(byteBuffer == null
&& ((byteBuffer = (ByteBuffer) FobsConfiguration.properties.get("ByteBuffer")) == null))
{
byteBuffer = ByteBuffer.allocateDirect(4*needDataSize);
if(Parser.avIsBigEndian()==false) byteBuffer.order(ByteOrder.LITTLE_ENDIAN);
FobsConfiguration.properties.put("ByteBuffer", byteBuffer);
}
//assert(byteBuffer!=null);
flag = parser.getNextFrame(byteBuffer, 0, needDataSize);
if(flag && data.length > 0)
{
byteBuffer.asIntBuffer().get(data);
}
}
In case you're using the latest version of FOBS you'll also need to make sure that the code block above that bit looks like this:
if ( dataNotOkay(obj, needDataSize) ) {
int []pixels = (int [])FobsConfiguration.properties.get("BufferedImageIntBuffer"); // <----- add this line
if (pixels == null) {
pixels = new int[needDataSize];
}
data = pixels;
buffer.setData(data);
} else {
data = (int[]) obj;
}
---------------------------
Now it's time to add the required libraries to the build path (or classpath). In case of 1, add JMF.jar (in /lib of wherever you installed (e)JMF). In case of 2, 3 and 4, you'll also need JMF.jar, from FOBS4JMF. In case of 2 and 3 (but NOT 4), also add fobs4jmf.jar. Next, set the native library locations for the .dll/.so/.jnilib files with Eclipse or -Djava.library.path . I myself use Eclipse for it (expand the jar in the build path screen), and have all files (jar, dll, etc) in the same dir. In the case of 4, even only setting it for JMF.jar seems to cover all native files in that directory.
---------------------------
Next, we'll test wether our setup is succesful so far, and we'll register our custom renderer. Both can be done with an application included with JMF, names JMStudio. However, we'll need to start it, with the compiled code of our project on the classpath. The application is JMStudio.class inside JMF.jar. With Eclipse this is easy.. create a new Run configuration (Run -> Run...) for a Java Application. On the "Main" tab make sure "include libraries when searching for a main class" is checked -> search... and find JMStudio.
When you launch, there will be a sort of media player there. Try to play some files to see what files will work and which won't (in the case of FOBS practically all will work). If the player gets frozen trying to play different files, it's most likely the issue with JavaSound that was mentioned in the beginning.
Next, we'll register our renderer. Backup up the settings we're about to change can be done by making a backup of the jmf.properties file. How to do so is well explained in the bottom (step 5) of this page:
http://fobs.sourceforge.net/f4jmf_first.htmlOur renderer (so it goes under the render tab) is called "org.llama.jmf.ByteBufferRenderer" Make sure it is at the TOP position, and don't forget to press Commit. If you had those issues with JavaSound, you can delete the JavaSound renderer. You can also completly remove sound support this way, simply remove everything on all tabs with "audio" in it (and Commit!). If you used option 3. make sure all com.omnividea.* are in the right place (near the top).
If the ByteBufferRenderer is correctly installed, you can still play a video in JMFStudio but there won't be any picture. You'll see some output on your console though.
------------------------
Wow! you made it this far.. we're about to see if it paid off. Open TestJMFVideoImage.java , edit the "String file =" line (make sure to use the right type of slashes for your platform). If you've applied the FOBS patch, also change the "ByteBufferRenderer.useFOBSPatch = false" line to "true".
and Run it..
You should see your video playing on the texture of a quad.
------------------------
If your video does not play at all..
- Check if the ByteBufferRenderer is set at the top of the renderers in JMStudio
- Did it play in JMStudio with a "normal" renderer?
No: something is wrong, check your paths, your -Djava.library.path, etc.
No: in case you choose 1) JMStudio does not play a lot of file formats, and even less on linux/mac. Try another file or FOBS.
No: Remove that damned JavaSound renderer or even everything sound related.
No: gimme the console output, stacktraces, etc.
Yes:..
- Did it "play" (the slider moved) in JMStudio with the ByteBufferRenderer set?
No: did you see (many times) "Error rendering video to texture. No glTexSubImage2D/OpenGL 1.2 support?" in the console? Your video card or driver does currently not support doing this.. but please tell me what you use.
No: gimme the console output, stacktraces, etc.
Yes:
Do not use mipmapping beyond that of the Test.
Change the line "ByteBufferRenderer.printframes = false;" to true. Run again and gimme the console output, stacktraces, etc. and tell me if the app kept running, printing frame information on the console, or crashed.
------------------------
My video plays, but looks very weird:
- How would you describe weird? The image seems ok except for the colors?
The image seems ok except for the colors: This could be a platform/endian issue. Two things you can try:
1. in JMFVideoImage.java there is a method setSize. Change all GL12.GL_BGRA to GL11.GL_ARGB and GL12.GL_BGR to GL11.GL_RGB.
2. (try seperate) In ByteBufferRenderer.java look for the line
nativebuffer.order(ByteOrder.nativeOrder()); //TODO: test on linux.
and change the ByteOrder to ByteOrder.BIG_ENDIAN or ByteOrder.LITTLE_ENDIAN.
- Or does it seem like several interleaved images?
You are likely using 1) and encountered an input format I was not able to test (currently supported: 32, 14 and 16 bit with masked int or byteordering). Try FOBS since this seems to use always the same input format.
Finally, interlaced files are not supported by FOBS afaik, dunno about Sun. It's not common to find interlaced video, except in DV camera footage.
---------------------
(Other) known issues:
- I did not test on linux/mac. Sorry, please let me know if (and what) works.
- WMV9 is not supported (go complain to Bill).
- Audio can make the scene stutter. Even with only video framerate can jump up and down. This is unfortunatly due to multithreading. There are some wait() and sleep() in the code, try playing around with them a bit. Also I might implement double buffering, and a jME audiorenderer some time, or work on some type of locking in FOBS. Don't hold your breath though.
- Multiple video streams are untested, should work in theory.
--------------------
Further stuff:
I've tested several files, including pretty high bit rate MPEG4. FOBS, and ecps. FOBS with patch handled them with pretty good performance. Playing an average XviD AVI file (624 x 352, around 1,500 kbit video only) my CPU usage was 2-5% using FOBS with patch, and about 7-18% using JMF from Sun. Of course the real test comes when playing some high def content, such as this nasty 720P XviD file (about 56 MB):
http://www.rdkleinpowera.de/videosctrendaug1/birch_hd_XviD82.aviThis was completly unplayable (cause of frame drops) using JMStudio with either FOBS or Sun's build. However, with FOBS+patch and using update(Texture, true) it only seemed to be dropping a few frames every now and then in jME. However, the same happened with all my other media players, though general CPU usage was less. MPEG4 really seems to enjoy spiking CPU usage. Mplayer (also based on FFMPEG, like FOBS) was best from my media players. And of course it also had to do audio.
Here's another file (MPEG2) to bring my renderer (and your PC) to it's knees:
ftp://ftp.heise.de/pub/ct/spezial/shuttle.mpgSize: 396.3 MB
Some things that could be improved: color space conversion done with shaders instead of CPU, double/tripple frame buffering, better packing of data for sending it to the GPU (tried that but still had some bug left in it that made it very slow instead).
Formats I tried with FOBS:
container:
AVI, MPG, MKV, OGM, 3GP all worked, MP4 was buggy, MOV crashed with 1 file, worked for others
video/audio codec:
MPEG1, MPEG2, XviD, DIVX, OGG, MP3, WMA
----------------
What you're still here? So.. hmm yes I know the code is a pain to look at (gotta love that use of static). It's more proof of concept than an actual lib at the moment.
License note: code is currently under LGPL (so is FOBS and so is FFMPEG), except for the example (jME license).
Let me know if this works for anyone else..