We closed this forum 18 June 2010. It has served us well since 2005 as the ALPHA forum did before it from 2002 to 2005. New discussions are ongoing at the new URL http://forum.processing.org. You'll need to sign up and get a new user account. We're sorry about that inconvenience, but we think it's better in the long run. The content on this forum will remain online.
IndexProgramming Questions & HelpVideo Capture,  Movie Playback,  Vision Libraries › Accessing quicktime movie frame by frame
Page Index Toggle Pages: 1
Accessing quicktime movie frame by frame (Read 2065 times)
Accessing quicktime movie frame by frame
Jan 19th, 2007, 6:29pm
 
Hi all.

I've got a quicktime movie (.dv clip at 720x480i) and i want to access it frame by frame (preferrably, field by field).  I have some basic processing code to step through it field by field.  The below code works... somewhat.  It sometimes repeats frames, since it's being accessed as time i believe.

Is there a way to access a quicktime movie in frames rather than in time?  ie, grab frame number 60, rather than time of 2.0...

Quote:

/*
* fieldstepper
*/


import processing.video.*;

Movie myMovie;

float pos = 0.0;
int field = 0;

void setup()
{
 size(720, 480);
 background(0);
 
 myMovie = new Movie(this, "/Users/me/testfile.dv");

 frameRate( 20 );
 
 // start at the beginning
 myMovie.jump( 0 );
 myMovie.read();
}

// this isn't called anymore, but just in case
void movieEvent(Movie myMovie) {
 myMovie.read();
}


void draw()
{
 fill( 255, 0, 0 );
 rect( 0, 0, width/2, height/2 );
 
 // first, plop down the movie
 image(myMovie, 0,0);
 
 // and draw the right field
 loadPixels();
 int idx1 = ((field+1)&0x01) * myMovie.width;
 int idx2 = ((field+0)&0x01) * myMovie.width;
 for( int y=0 ; y<myMovie.height ; y+=2 ) {
   int p1 = idx1;
   int p2 = idx2;
   for( int x=0 ; x<myMovie.width ; x++ ) {
     pixels[ p2++ ] = pixels[ p1++ ];
   }
   idx1 = idx1 + myMovie.width + myMovie.width;
   idx2 = idx2 + myMovie.width + myMovie.width;
 }
 updatePixels();

}

void mousePressed()
{
 if( mouseButton == LEFT ) { // advance to next field
   field ++;
   if( field > 1 ) {
     pos = constrain( pos + (1.0/29.97), 0, myMovie.duration() );
     myMovie.jump( pos );
     myMovie.read();
     field = 0;
   }
 } else {
   field --;
   if( field < 0 ) { // go back to the previous one
     pos = constrain( pos - (1.0/29.97), 0, myMovie.duration() );
     myMovie.jump( pos );
     myMovie.read();
     field = 1;
   }
 }
 println( "POS: " + pos + " " + field + " / " + myMovie.duration() );
}
Re: Accessing quicktime movie frame by frame
Reply #1 - Jan 19th, 2007, 8:01pm
 
not specifically for frames or fields, though in theory, movieEvent() will do that, in the sense that it will only be called when there's a new frame.

alternatively, the capture/movie classes are very small, you might try making your own version that does what you need. there might be a qtjava example that does what you want, which could be adopted.
Re: Accessing quicktime movie frame by frame
Reply #2 - Jan 19th, 2007, 8:16pm
 
understood.

I looked through the quicktime apis for objective c and java, and i only saw mechanisms for accessing it via time... i was hoping that there was some workaround in process for processing.. Wink

The thing is that I need to say "move forward one frame", on command, not while playing the movie back.  It seems as though the movieEvent() only gets called when looping or playing the movie.

(As a sidenote, i'm also looking into getting libdv working with java, and subsequently processing, for this purpose as well.)
Re: Accessing quicktime movie frame by frame
Reply #3 - Jan 19th, 2007, 8:35pm
 
myMovie.speed(0) is necessary as an init I've found for frame by frame stuff. Otherwise you have this battle going on with the playhead. It should eliminate all the calls to myMovie.read() you're doing.
Re: Accessing quicktime movie frame by frame
Reply #4 - Feb 16th, 2010, 8:05pm
 
This allows me to output a .png of a .mov file every 10th of a second.  It works ok, somewhat choppy.  Not sure if all the delays at the end of the script are needed, so feel free to remove them to speed things up.
-Seb

Code:
import processing.video.*;

Movie myMovie;

float framesPerSecond = .1;
float currentSecond = 0;

void setup() {
size(640, 480, P3D);
background(0);
// Load and play the video in a loop
myMovie = new Movie(this, "hangover.mov");
myMovie.speed(1);
myMovie.play();

}

void movieEvent(Movie myMovie) {
myMovie.read();
}

void draw() {
myMovie.jump(currentSecond);
delay(300);
image(myMovie,0,0);
currentSecond += framesPerSecond;
delay(300);
saveFrame("images/output####.png");
delay(300);
}
Page Index Toggle Pages: 1