fbo looping

Hi,
I’ve been trying to iterate through 96 or so fbos through a for loop that constantly record the last 96 frames. Then I want to be able to jump back x amount of frames and loop on only the last 50 or so frames until its released again. I think I did it but it’s super choppy and slow. I was hoping there wouldn’t be too much latency using fbos but maybe there is a more memory/cpu efficient way of using them or maybe there’s an alternative trick? if anyone has ideas it would be great. I can post some code but its pretty self explanatory.

Hi there,

In general FBO’s should be used sparingly as they take up a ton of video memory, which is much more limited than your CPU memory. My rule of thumb is to never allocate more FBO surface than twice the number of pixels on your screen.

For your case, try having just 1 FBO and one image, the FBO you draw into and then immediately readPixels into an ofPixels object. Keeping 96 ofPixels around should be no problem, as long as you are assigning them by reference (using pointers, not copying on each assign)

Then when you want to show one of the images in your queue, take an image, setFromPixels(), and call update() and show it.

If this is confusing, post a little example and we can recode it together to use a different approach.

Thank you so much. I never even thought about ofPixels objects. I’ll look into it and let you know how it goes. Love your work.

I am officially retarded when it comes to pointers. I read it, I understand it, but then doing it a vice for me. I got this working before I tried implementing pointers. Don’t know what I’m doing wrong. Theres something going wrong when I try if(pix[i]->isAllocated()) and pix[i]->allocate(FBOXY,FBOXY,OF_IMAGE_COLOR_ALPHA); I think. thanks for the help.

.h

  
  
#pragma once  
  
#define FBOXY 1024;  
  
#include "ofMain.h"  
#include "ofxThreadedVideo.h"  
  
class testApp : public ofBaseApp{  
public:  
      
    void setup();  
    void update();  
    void draw();  
  
    void keyPressed  (int key);  
    void keyReleased(int key);  
    void mouseMoved(int x, int y );  
    void mouseDragged(int x, int y, int button);  
    void mousePressed(int x, int y, int button);  
    void mouseReleased(int x, int y, int button);  
    void windowResized(int w, int h);  
    void dragEvent(ofDragInfo dragInfo);  
    void gotMessage(ofMessage msg);  
	  
  
	int loopBool;  
	int loopPlay;  
	int loopCount;  
	int width;  
    int height;   
	  
	  
    ofFbo       fbo;  
	ofImage     img;  
	ofPixels * pix[96];  
  
	  
      
  
	  
	// Movies Threads  
	ofDirectory files;  
      
	ofxThreadedVideo video1;  
	ofxThreadedVideo video2;  
	void threadedVideoEvent(ofxThreadedVideoEvent & event);  
	  
};  
  
  

.cpp

  
  
#include "testApp.h"  
  
//--------------------------------------------------------------  
void testApp::setup(){  
    ofEnableAlphaBlending();  
    ofSetFrameRate(24);  
    files.allowExt("mp4");  
    files.listDir("/Users/houstonzombie/Documents/vjvideos/drive_in/"); // put a video path here with several video files in a folder  
      
    video1.loadMovie(files.getPath(ofRandom(files.numFiles())));  
    video2.loadMovie(files.getPath(ofRandom(files.numFiles())));  
	  
	video1.setPaused(false);  
	video2.setPaused(false);  
	video1.setUseTexture(true);  
	video2.setUseTexture(true);  
	ofAddListener(video1.threadedVideoEvent, this, &testApp::threadedVideoEvent);  
    ofAddListener(video2.threadedVideoEvent, this, &testApp::threadedVideoEvent);  
	  
	  
    loopBool = false;  
	loopPlay = false;  
	loopCount = 0;  
    width = 1080;  
    height = 720;  
	fbo.allocate(FBOXY,FBOXY,GL_RGBA);  
	img.allocate(FBOXY, FBOXY, OF_IMAGE_COLOR_ALPHA);  
	  
	for ( int i = 0; i<96;i++){  
		if(pix[i]->isAllocated())  {  
		}else{  
			pix[i]->allocate(FBOXY,FBOXY,OF_IMAGE_COLOR_ALPHA);  
		}  
	}  
	  
    fbo.allocate(width,height);  
    ofSetWindowShape(width, height);  
      
	  
	  
	fbo.begin();  
    ofClear(0,0,0,255);  
    fbo.end();  
	  
	  
}  
  
//--------------------------------------------------------------  
void testApp::update(){  
	  
	video1.play();  
	video1.update();  
	video1.setVolume(0);  
	video2.play();  
	video2.update();  
    video2.setVolume(0);  
	  
    fbo.begin();  
	video1.draw(0,0,width,height);  
    fbo.end();  
      
  
	if(loopCount==96){  
		loopCount=0;  
		loopBool=false;  
	}  
	if (loopBool == true){  
		fbo.readToPixels(*pix[loopCount]);  
	}  
	img.setFromPixels(*pix[loopCount]);  
	  
	  
	loopCount++;  
	  
	  
	  
	  
	  
}  
  
//--------------------------------------------------------------  
void testApp::draw(){  
	ofBackground(0, 0, 0);  
	  
    ofSetColor(255,255);  
	glEnable(GL_SMOOTH);  
	glEnable(GL_BLEND);  
	glBlendFunc(GL_ONE, GL_ZERO);  
  
	if (loopPlay == false){  
		fbo.draw(0,0,FBOXY,FBOXY);  
		  
	}else if (loopPlay == true){  
		img.draw(0,0,FBOXY,FBOXY);		  
		  
	}  
  
}  
  
void testApp::threadedVideoEvent(ofxThreadedVideoEvent & event){  
    ofLogVerbose() << "VideoEvent:" << event.eventTypeAsString << "for" << event.path;  
}  
  
//--------------------------------------------------------------  
void testApp::keyPressed(int key){  
	switch (key) {  
  
		case '1':  
			loopCount = 0;  
			loopPlay = true;  
			loopBool = true;  
			  
			break;  
		case '2:  
			loopPlay = false;  
			break;  
		default:  
			break;  
	}  
	  
	  
}  
  
  
  

I think using a vector<ofPixels*> pix may make it a bit clearer.

change

  
ofPixels * pix[96];   

to

  
vector<ofPixels*> pix;  
  

after

  
img.allocate(FBOXY, FBOXY, OF_IMAGE_COLOR_ALPHA);  

do

  
for ( int i = 0; i<96;i++){   
  ofPixels* p = new ofPixels();  
  pix.push_back(p);  
}  

nice part about vectors is that you can then use pix.size() as opposed to 96 if you need to loop through the “array”(actually vector) of ofPixel pointers again

I actually think you can get away without pointers at all, as long as you aren’t ever reassigning into the array

brief code:

  
  
//testApp.h  
vector<ofPixels> pix;  
  
//.cpp  
if(pix.size() < loopCount-1){  
  pix.push_back(ofPixels());  
}  
  
if(!pix[loopCount].isAllocated()){   
     pix[loopCount].allocate(FBOXY,FBOXY,OF_IMAGE_COLOR_ALPHA);  
}  
fbo.readPixels(pix[loopCount].getPixelsRef());  
//...  
//to update the image  
image.setFromPixels(pix[loopCount].getPixelsRef());  
  
  
  
  

Got it working! Thank you so much.