JFjr - the JMF/FOBS/jME video renderer

I didn't make any changes except for a method that returns a reference to the player.



I added your suggested lines to the stopMovie method but the leak is still there.



Could it have something to do with line 208 (ref to a fresh copy of the file from your website  :)) of the file?


data = ByteBuffer.allocateDirect(size*size*4).order(ByteOrder.nativeOrder());



Also I have trouble locating the reference to the static field you wrote about.

Thanks a lot for your time. It's really nice to get some help on this.

No. Only one such buffer is created for each video file. When the Player dissappears, there's only 1 reference left to it, a static one which is replaced if you play a new video file. Even if for some reason (eg cause you keep a reference to Player somewhere) it was not collected… even with an 800x600 sized movie, it's less than 2 MB per movie. You should be able to "leak" that way more than 5 times.



As for the change, you have to use stopMovie for my change to work (and not stop the player yourself like you do now).



I'm afraid you'll have to debug your program to trace where this memory leak is coming from. Now's as good a time as any to learn profiling, I guess :slight_smile:

okay, tried the profiler before calling stopMovie from my game and after altering the code as you just suggested. Clearly that did the trick regarding memory usage but the app still freezes at the same spot as always. I get "Out of memory!" in the standard error stream. Will look for place that outputs that message now…

If you use YourKit, I think it has an option to take a memory snapshot on low memory.

Yes it has such an option but I don't know how it works. When I get the "out of memory" message on the error stream only 13.3 MB of 41.3 MB is used on the heap. On the other hand 10.2 MB of 10.4 MB of the non-heap memory is used.

That doesn't mean anything, that number is the just the allocation, if more is needed the non heap memory will just expand, as long as there's room left.



Further, the problem with many profilers is they don't profile native memory allocations. Use the windows task manager or something like that (I like process explorer from sysinternals.com myself, it can make a nice graph just for your procress) and you can see it's real size… that is it's real allocation. Just cause it's allocated does not mean it's used.



Anyway, here you should be able to see if there's a jump in allocation each time you start a new video. Try giving more memory to the VM with the commandline parameters -Xms and -Xmx if you have to (see http://blogs.sun.com/roller/resources/watt/jvm-options-list.html for usage).



When I use the JMStudio app with FOBS I can open many files in a row without it increasing much, when I used the Java2DRenderer that my renderer is based on. Maybe there are some threads that get locked up with my implementation, I'll take a look at that. You can begin with:



synchronized public void stopMovie() {
      try {
         jmfplayer.close();
         jmfplayer.deallocate();
         jmfplayer = null;
         System.gc();
         failed = true;
         this.notifyAll();
      } catch (Exception ignored) {
      }
   }



And for those using syncToFrameRate (not relevant to you I suppose)..


public boolean update(Texture texture, boolean syncToFrameRate) {
      
      if (syncToFrameRate) {
         synchronized(this) {
            while (!failed && lastupdated >= framecounter) {
               try {
                  this.wait();
               } catch (InterruptedException e) {
               }
            }
         }
      }

Hi again



I tried using process explorer and just like you predicted it showed that more memory is being used each time a video is run. Actually a small amount of memory is freed when the movie ends but not enough. In the end the process ends up using 164.8 MB memory and freezes. I'll be away until sunday from now so I wont look at it until then. Thanks again for the help

I replayed the same file a few times here, and I only got a very small increase in memory use each time. I'll try using two different files next time though.



What file format are you using?

I'm playing 600x800 divx compressed avi files.

I've tried what I can to make it leak memory, but to no avail. I've played the same files several times, other files, other formats. It always returns to the same memory usage when I play the same file again.



Maybe there is some magic in my small changes that'll work for you, so here is a link to the updated JMFVideoImage and test that loads several files. You can change the starter movie at the top, and the rest at the bottom. It assumes you have patched FOBS.



http://www.tijl.demon.nl/jme/JFjr/temp/JMFVideoImage.java

http://www.tijl.demon.nl/jme/JFjr/temp/TestJMFVideoImage.java



So, you can try putting links to your own files in the test. If that still leaks, then maybe try some different formats or something.

Good news! My game is nok leaking memory anymore!



I read about YourKit and then used it to find the places in my code where there was leaks. Basically I just had to null a bunch of references and add a single stopMovie call at one place. My god it feels good to be without that leak  :smiley:



Thanks a lot for the help!

But now a new problem have arrived  :slight_smile: The line


jmfplayer.close();


in stopMovie takes 3 seconds to perform when I play my largest movie. Is this supposed to be so?

Then we're back to the point where I know very little about JMF. Are you sure it's the close? (not the System.gc(), which you can remove if you want).



I guess that's kind of long… maybe you can do the close from a new thread and forget about it. I think jmf can handle that.

Ok, so now I've got JMF and jME up and running together now too. Question to Llama: Do you still want user feedback for your code, or have you stopped developing on this matter for now?

I'll probably update the code a bit in the future for rectangular textures… 



I'm not using it myself though at the moment, and like I said here, it's more a proof of concept than an actual API. If you have any comments I'll see what I can do though…

Have you had any thoughts on how to flip the movie without having to use the quadhack you implemented? I actually haven't used jmf myself, maybe I should have a look into that and find out myself.

Flipping the texture coordinates would be easiest I think.

Uhumm, one obvious answer which, of course, works. 



Thanks very much for the quick answer, I'd better use my brain befor I post in future  :slight_smile:

@llama



Have you ever had trouble with the speed your movies play? I have a configuration here with jme + your videorenderer playing on three different PCs. When I start the movies on all three PCs at the same time, they all actually play at a different speed. I've done several tests and now found out, that for some reason the windows time gets messed up. On the PCs where the movie is played too fast, the time will be ahead for the number of seconds the movie ended to early. Quite strange… If I restart the PC, its time is back to normal. If I play the videos in jmstudio, the same thing happens. I'm not sure where to look for the error, seems it must be something in the jmf configuration. Im using windows, jmf + fobs + fobspatch. If you have any thoughts, thanks a lot. If not it's probably best to take this question to the jmf forums I think.

Can't recall having that problem, but if the same happens in JMStudio than probably it's not due to my code, as you say.



Did you try JMStudio without FOBS too, and did you still get this problem?

Then it's likely a JMF problem… and since Sun decided to let JMF die a slow, cold and lonely death… I think they have a mailinglist still somewhat active though: http://archives.java.sun.com/jmf-interest.html



And I believe there's some opensource projects to replace JMF too…