Feedback: Saving video frames for delayed playback


#1

Hi, I want to have two playbacks of the same video file where the only difference is the current playback position. One should play the latest frame, the other on should lag behind (e.g. 60 frames). Currently, I am using a .mov as a source, but later I would like to use the webcam.

I read through the OF documentation but couldn’t identify a suitable function so I came up with the following solution:

Use the ofVideoPlayer, apply .getPixels() on the current frame to create an ofImage and then push this image in a vector. Later draw the images stored in the vector.

class ofApp : public ofBaseApp{
    ofVideoPlayer srcVid;
    vector<ofImage> frameBuffer;
    int playbackOffSet = 0;
}
void ofApp::setup(){ 
    srcVid.load("movies/fingers.mov");
    srcVid.setLoopState(OF_LOOP_NORMAL);
    srcVid.play();   
}
void ofApp::update(){
    srcVid.update();
}

void ofApp::draw(){

   // saving the current frame to a vector
    ofPixels pixTemp = srcVid.getPixels();
    ofImage imgTemp(pixTemp);
    frameBuffer.push_back(imgTemp);

    // limit the number of saved frames
    if(frameBuffer.size() > 60) frameBuffer.erase(frameBuffer.begin());

    // define the playback offset
    if(frameBuffer.size() < 60) playbackOffSet = 1;
    else playbackOffSet = CLAMP(ofMap(mouseX, 0, ofGetWidth(), 0, 59), 1, 59);
    
    // draw the video from the player, and the images out of the vector
    srcVid.draw(0,0);
    frameBuffer[frameBuffer.size()-playbackOffSet].draw(srcVid.getWidth(),
                                                        0,
                                                        srcVid.getWidth(),
                                                        srcVid.getHeight());   
}

The solution works but is very heavy on memory. I was wondering if there is a smarter way to do that and would appreciate any input.

Thanks a lot!


#2

Hello there,

You could look for ofImageSequence which is doing what you want but instead of using ofImage it uses ofPixels (which has no texture).
I used it a while ago and added some functionalities here:

You could also look at more complex addons like ofxHPVPlayer that are using compression.

Good luck!
J


#3

Hello @niklasM
Just wondering about your need, I would try to solve this with an array of ofFbos with the fixed number of 60.
I would make a counter to increment in each frame until 60 and write the actual frame to the current position
and the next frame to the one you are writing is the oldest in the array.

this way you have always 60 frames in your GPU but no more than that. does it makes sense?


#4

thank you. this looks promising. i will try this soon.


#5

thank you. do you suggest that an array with 60 spots is less processor heavy then a vector that does not get bigger then 60?


#6

sorry, I meant a vector