Here you go.
Note: Depending on the size of the video, you may need to increase the max memory (File -> Preferences) since the entire "buffer" is kept in memory as an array of PImages. It worked fine for me with a 15 second delay (450 frames @ 30 fps) and a frame size of 320x240 when I had the memory set to 256mb. The buffer only needs to accommodate the framerate of the *input* so keep that in mind when you're initializing it or the timing will be off.
This sketch uses the "station.mov" movie that is included with the examples when you download processing, you'll need that in the "data" folder to try this out.
You'll need to replace the Movie with a Capture object so it will work with a camera instead of a pre-recorded movie. The VideoBuffer class doesn't care where the images come from, but they DO need to be the same size.
Also, the output will be black until the buffer is full (for obvious reasons). You could easily modify the VideoBuffer class to show an "initial" image while the buffer is filling up, but I'll leave that to you since I have no idea about your specific implementation needs.
Code:
import processing.video.*;
VideoBuffer vb;
Movie myMovie;
void setup()
{
size(300,300, P3D);
myMovie = new Movie(this, "station.mov");
vb = new VideoBuffer(30, 160, 120);
myMovie.loop();
}
void movieEvent(Movie m)
{
m.read();
vb.addFrame( m );
}
void draw()
{
image( vb.getFrame(), 100, 100 );
image( myMovie, 0, 0 );
}
class VideoBuffer
{
PImage[] buffer;
int inputFrame = 0;
int outputFrame = 0;
int frameWidth = 0;
int frameHeight = 0;
/*
parameters:
frames - the number of frames in the buffer (fps * duration)
width - the width of the video
height - the height of the video
*/
VideoBuffer( int frames, int width, int height )
{
buffer = new PImage[frames];
for(int i = 0; i < frames; i++)
{
this.buffer[i] = new PImage(width, height);
}
this.inputFrame = frames - 1;
this.outputFrame = 0;
this.frameWidth = width;
this.frameHeight = height;
}
// return the current "playback" frame.
PImage getFrame()
{
return this.buffer[this.outputFrame];
}
// Add a new frame to the buffer.
void addFrame( PImage frame )
{
// copy the new frame into the buffer.
System.arraycopy(frame.pixels, 0, this.buffer[this.inputFrame].pixels, 0, this.frameWidth * this.frameHeight);
// advance the input and output indexes
this.inputFrame++;
this.outputFrame++;
// wrap the values..
if(this.inputFrame >= this.buffer.length)
{
this.inputFrame = 0;
}
if(this.outputFrame >= this.buffer.length)
{
this.outputFrame = 0;
}
}
}