multi output poly~ for movies

piwolf's icon

So I am starting to attempt to use poly~'s awesome loading ability for movies along with a multilayer media server type application. I love the responsiveness of the bank loader in the VPS4 tutorial. First I just copied 4 of those and used them to feed composite slabs and had ok results. lots of resources being used though. what i want is a single loader that sprays out to a duplicate dropmenu for each layer and selecting from the menu in a layer sends that single instance of poly~ to the corresponding layer. Any pointers or past experience with this appreciated. I will share what i find as I go. Gurus please let me know if this is a rough or already proven bad path.

Thanks!

B

piwolf's icon

so i altered the vps poly movie holder and the mbank to have 8 outputs and controls for the gate object that I used for the outputs. The setup works but I am still getting this periodic stalls in video that I am having problems tracking down the cause of. I am using animation codec 4 plane mov's. Using Vade's basic optimization patches I have alot of success with basic playback but loading a movie in the background while another plays is a major issue. with or without asyncread I get stalls. Is there a practical cap when it comes to file size when working with HD movies in Jitter? I frequently need to deal with files up to 3 or 4 gigs each. I have tried so many different load and read methods and have never gotten the results I am hoping for. I guess next step is to start using mpeg full i frame like what i use for hippo and pandora and see how jitter likes that file type. Then i could get the file sizes down considerably. Any tips on this background layer load issue would be a huge help and actually I would be willing to pay for a sweet patch that has clean loading for 8 layers of HD. Im using a screaming i7 machine that shouldnt have any trouble with this. I know way slower hardware that has run 8 layers of HD on the hippo software which is built right in C. I hope there is a way to allow jitter to compete.

Jesse's icon

I'm not entirely familiar with the poly~ movie playback method you've referenced, but I can tell you that in my experience one way to work around CPU contention issues in Max is to work at a level that allows you to create/destroy your own threads. At this point I believe this is either the C/C++ or Java API's.

I've built modules in Java that do extensive network retrieval of XML files via HTTP calls, and found that executing these in the main scheduler thread caused all sorts of timing issues in the parent patch, which was itself quite complex. I believe that this was due to the fact that some of the retrieval methods were blocking. The solution was to use the Java threading API to create a separate background thread and execute there, which showed no noticeable impact on the patch performance. The only downside to this approach is that it can necessitate that you become familiar with issues around concurrence, which can be a bit opaque if you don't have experience in this area.

There is a brief reference to this technique on page 42 of the PDF file "WritingMaxExternalsInJava.pdf" - "Using Java threads for computationally intensive tasks."

It's pretty easy to imagine that you could create a compact Java class that simply reads specified .MOV files into a jit.qt.movie object on a background thread, then notifies the parent patch once it is loaded. You would have to use the Java context to play out your movie frames, but this would be fairly trivial, and those frames could easily be passed off to whatever shader/gl objects you desire.

Hope that helps somewhat...

piwolf's icon

thanks man, an approach I havent tried and I have written small stuff in Java that I needed in Max before. will give it a shot.

B

Rob Ramirez's icon

also might want to try apple intermediate codec.

piwolf's icon

interesting; would a codec change really affect this behavior? i was just talking to my broadcast cohort who is really hyped about it for final cut ingestion. I wanted to start trying it anyway. we will see...

piwolf's icon

just wanted to post an update that I was able to get much more solid results with the poly method with some tweaking to the scheduler settings and running poly in local mode to give it its own thread. still looking into the java movie reader method because i think there is some serious potential there but its not written yet.

Jesse's icon

I gave it a stab -- not sure if it does the trick for you, but I've attached the source code. [EDIT] I'm trying to attach the source code. Getting mime type errors uploading a zip file.

I loaded some pretty large movie files and found pretty decent performance, particularly after a file had been loaded at least once. I'm not sure if QT is doing some caching behind the scenes, but there were definitely some unpredictable hiccups upon first load.

Max Patch
Copy patch and select New From Clipboard in Max.

Here's the enclosing test patch - you can adjust for your needs. I'm basically using the notification from the Java class to control a gate that filters incoming bang messages while the movie is loading.

38.file.zip
zip
piwolf's icon

yeah i would love to check it out but there is no attachment.

Jesse's icon

Trying again...

No luck. Cycling, why can't I upload a zip file?

55.file.zip
zip
reno-'s icon

maybe you can paste the code direct like a message ?

r

Jesse's icon

Ok, here it is.

ThreadedMoviePlayer.java_____________________


import com.cycling74.jitter.JitterMatrix;
import com.cycling74.jitter.JitterObject;
import com.cycling74.max.Atom;
import com.cycling74.max.MaxObject;

public class ThreadedMoviePlayer extends MaxObject
{
    private JitterMatrix mx;
    private JitterObject moviePlayer;
    private Thread t;

    public ThreadedMoviePlayer( int width, int height )
    {
        mx = new JitterMatrix( 4, "char", width, height );
        moviePlayer = new JitterObject("jit.qt.movie");
        moviePlayer.setAttr("dim", new int[] { width, height } );
    }

    public void bang()
    {
        moviePlayer.matrixcalc( mx , mx );
        outlet( 0, "jit_matrix", mx.getName() );
    }

    public void read( final String path )
    {

        // remove the reference if t has already been created.
        if( t != null )
        {
            t = null;
        }

        // create a new thread
        t = new Thread()
        {
            public void run()
            {
                Atom[] result = moviePlayer.send( "asyncread", path );                

                outlet( getInfoIdx(), "read", result );
            }
        };

        t.start();
    }
}