multiple video player

#1

Hi all,

(this comes from previous thread http://forum.openframeworks.cc/t/threaded-video-player/1335/1)

I have a problem playing multiple videos at the same time.

  • I’m running a MBP, OSX 10.7, 2,4Ghz Intel Core i5
  • 4Go 1067 MHz DDR3
  • NVIDIA GeForce GT 330M 256 MB
  • Movies weight between 76 and 114 Mo, between 28 and 50 seconds, Quicktime (.mov), 240 x 340 px, PNG Codec (Linear PCM), bitrate 21 800

Movies are videoprojected and I use a Kinect to detect people’s position. According to people’s position, I play, rewind or stop the movies. The problem comes when several movies are played at the same time, they all slow down.

Here is the source code.

Thanks !

Multiple-MoviePlayer.zip

#2

ok that’s hard for me to debug without movies or a kinect :wink:

I think we should start out simple…no classes…no osc…let’s just test the video playback…

Try this in an a fresh emptyExample:

testApp.h needs to have:

  
ofVideoPlayer videos[3];  

testApp.cpp

  
#include "testApp.h"  
  
//--------------------------------------------------------------  
void testApp::setup(){  
	videos[0].loadMovie("<your movie path>");   
	videos[1].loadMovie("<your movie path>");  
	videos[2].loadMovie("<your movie path>");  
}  
  
//--------------------------------------------------------------  
void testApp::update(){  
	ofBackground(0, 0, 0);  
	videos[0].update();  
	videos[1].update();  
	videos[2].update();  
}  
  
//--------------------------------------------------------------  
void testApp::draw(){  
	ofSetColor(255, 255, 255);  
	videos[0].draw(0,0);  
	videos[1].draw(videos[0].getWidth(), 0);  
	videos[2].draw(videos[0].getWidth() + videos[1].getWidth(), 0);  
}  
  
//--------------------------------------------------------------  
void testApp::keyPressed(int key){  
	switch (key) {  
		case '1':  
			videos[0].play();  
			break;  
		case '2':  
			videos[1].play();  
			break;  
		case '3':  
			videos[2].play();  
			break;  
		case '4':  
			videos[0].stop();  
			break;  
		case '5':  
			videos[1].stop();  
			break;  
		case '6':  
			videos[2].stop();  
			break;  
		default:  
			break;  
	}  
}  
  

#3

Ok, so this example works for me as long as movies are being played without interruption.

If for example I make “play” and “stop” repeatedly on the first movie, it will make the other movies lag (a very short lag, when I press “play”).

#4

Ah yes, try substituting stop for setPaused()

At the moment there is not getPaused or togglePaused on ofVideoPlayer, so either use goVideoPlayer (where they are implemented from memory) or:

in testApp.h put a

  
#define MAX_VIDEOS 3  

above the class declaration

and then declare:

  
ofVideoPlayer	videos[MAX_VIDEOS];  
bool			bPause[MAX_VIDEOS];  
string			videoPaths[MAX_VIDEOS];  

and in testApp.cpp you can now do a variation on:

  
#include "testApp.h"  
  
//--------------------------------------------------------------  
void testApp::setup(){  
	  
	ofSetLogLevel(OF_LOG_VERBOSE);  
	  
	videoPaths[0] = "<your movie path>";  
	videoPaths[1] = "<your movie path>";  
	videoPaths[2] = "<your movie path>";  
	  
	for (int i = 0; i < MAX_VIDEOS; i++) {  
		ofLog(OF_LOG_VERBOSE, "Attempting to load: " + videoPaths[i]);  
		bPause[i] = true;  
		videos[i].loadMovie(videoPaths[i]);  
		videos[i].play();  
		videos[i].setPaused(bPause[i]);  
	}  
	  
}  
  
//--------------------------------------------------------------  
void testApp::update(){  
	ofBackground(0, 0, 0);  
	for (int i = 0; i < MAX_VIDEOS; i++) {  
		videos[i].update();  
	}  
}  
  
//--------------------------------------------------------------  
void testApp::draw(){  
	ofSetColor(255, 255, 255);  
	int xOffset = 0;  
	for (int i = 0; i < MAX_VIDEOS; i++) {  
		videos[i].draw(xOffset,0);			// could use glTranslatef(xOffset,0,0) or ofTranslate(xOffset,0,0) instead of draw(xOffset,0)  
		xOffset += videos[i].getWidth();  
	}  
}  
  
//--------------------------------------------------------------  
void testApp::keyPressed(int key){  
	  
	if (key - '1' < MAX_VIDEOS) {		// so now 1,2,3 toggle pause on and off  
		int whichVideo = key - '1';		// note the single quote's around '1' ('1' as a char = 48 so we get key = 48 - '1'(48) = 0  
		ofLog(OF_LOG_VERBOSE, "Toggle pause on: " + videoPaths[whichVideo] + "...change " + ofToString(bPause[whichVideo]) + " ...");  
		videos[whichVideo].setPaused(bPause[whichVideo] ^= true); // the ^= toggles a bool  
		ofLog(OF_LOG_VERBOSE, "to: " + ofToString(bPause[whichVideo]));  
	}  
}  
  

#5

Thanks for that, but it didn’t resolve the lag… Do you have that lag problem on your computer ?

#6

Hi, you may want to try re-encoding those videos. I imagine that PNG sequence compression is going to be slow to decode. I could be wrong, never worked with PNG in video, but for still images I know it usually takes a while to load/save PNGs.

I usually use MJPEG for anything with video in oF. File sizes are bigger than h264 and mpeg4, but mjpeg is very fast to decode, and uses very little processor power compared to other codecs.

I hope this helps.

ofVideoPlayer certain .mov formats throw error on exit
#7

Hi Tim, can you give some more details about your preferred codec settings? (m-jpeg A, B, container, compression, etc.). I’ve been driving myself crazy lately trying to playback HD video without any dropped frames, and am curious to see exactly what works best for you. I’ve been trying .mov files with photo-Jpeg compression, or .mov H264, but set to Keyframe every frame. Both of these are ok, but I still get the odd dropped frame.

#8

drosen, I use ffmpeg to convert everything, and I’m not sure if it’s built in mjepg compressor is type A or B, but I would guess it is B, because according to wikipedia, type B strips out some header data for each frame as it should be the same for all frames, and I know ffmpeg’s mjpegs are like this.

I’ve used both .mov containers and .avi. I haven’t noticed any difference in performance between containers though.

I use linux, but I know ffmpeg can be installed on mac and windows too, just may be a bit more complicated.

Here’s how you would compress things with mjpeg for oF projects:

  
ffmpeg -i input_file.mov -vcodec mjpeg -sameq output_file.mov  

I’m not sure how photo-jpeg compares to mjpeg, but I know h264 is probably going to be the slowest compression to use for high performance playback, though maybe forcing keyframes every frame would make it faster.

#9

If you’re on linux then you are probably using GStreamer for playback. I tend not to have any playback issues with GStreamer, but on OSX its a different story. I’ve tried a bunch of things now (including some mjpeg tests), and it may be that my issues are codec independent…

#10

For marcanudo - have you tried using QTkit for video? on OSX it generally performs much better than the older quick-time player. Alternatively have you tried gameover’s goVideoPlayer? Each of these solves a different problem, although I don’t think they can be used together.

#11

It does, thanx for the info :slight_smile:

PS: Is there a reference page for video specs(best/working/should work settings) in oF ?

#12

Thanx for this info :slight_smile:

#13

A small thing that’s been niggling me for a while is how to pause/unpause a video without getting that stutter, or blocking behaviour that marcanudo was seeing (I see it too on mac and windows)…

I did some looking into this whole pause/un-pause ‘glitchiness’ or ‘stutter’ for a project I did recently and I found a super fast way to avoid the glitch that happens when calling setPause on an ofVideoPlayer. It’s a bit of hack, but what I now do is just not call update() on the movie I want to pause! Not sure what the ramifications of this are with HUGE numbers of ofVideoPlayer instances, but for 6-12 I had no problem whatsoever and can’t see why it wouldn’t work for a lot more -> basically update() on an ofVideoPlayer (using Quicktime anyways) just calls MovieTask which is kind of Quicktime’s equivalent of update…so not calling that is essentially pausing the update of the movie!

I wrote a replacement for goThreadedVideo/goVideoPlayer called ofxThreadedVideo that implements this method (setFastPause), but really it could be done with an array or vector of bools if you want a simpler approach…more fitting with the above examples…

Playing and blending multiple videos