threaded video player

hrmm, is setLoopState working properly? When ever I run this function, I get an EXC_BAD_ACCESS crash. Any ideas?

Hi Guys,
Is it possible to thread the loaders of multiple players, so say I have 6 VideoPlayers and I want them all to have non blocking loaders? I got errors when I tried to declare more than one threaded player about the thread being blocked.

My question is similar to the previous one. I’m trying to make a video player that continuously cross-fades between some video clips. What I have works fine except for a hiccup (from loading the next clip) when starting the cross-fade.

Using goThreadedVideo I was hoping to be able to load into two different queues. But it doesn’t seem that the addon supports more than 1 goThreadedVideo object. Is there a way to work around this, or it impossible because of the way the video system is set up?

I think gameover mentioned earlier that the problem with two videos using the videoThreader is that they both try to load textures into the Main openGL thread which cannot be threaded. Thats my understanding…

Let me know if you figure out a clever solution. Right now mine is to open and close several ofVideoPlayers, delete memory and declare a new VideoPlayer, which sort of works but after 1 hour the app crashes.

Hey Seh4b, I haven’t found any good solution yet.
If you wouldn’t mind sending me / posting an example of the code your testing, maybe we could try debugging it together.

There are two ways goThreadedVideo will block a request to load a new video.

Which error are you getting?

  
Load BLOCKED by reload before draw/update  

or

  
Load BLOCKED by already thread loading  

It’s totally possible to have several instances of goThreadedVideo running and loading ‘at the same time’ - although they actually can’t load simultaneously. This is because of the nature of mixing threads with quicktime. The issue with openGL is a side issue.

At the top of goThreadedVideo you’ll see

  
static bool loading  

and a little lower you’ll see:

  
&& !loading                    // ...and that no other instance is also loading (this is optional, but recommended ;-)  

You can try commenting out this line…but what tends to happen is that the threadedFunction (in one or more instances of goThreadedVideo) will eventually call a loadMovie at exactly the same time. This makes Quicktime choke, since it is not able to handle simultaneous requests.

By it’s nature we need to make calls to Quicktime in serial.

The way I get around this is to use a series of events to check that each movie I want to load has been loaded, and then load the next one.

It would of course be better if this was all happening ‘invisibly’ inside the class, but it can be done explicitly easily enough.

Hopefully the attached example will help you find a way around these limitations.

src.zip

I think I’m making good progress now, but the issues I was having before seemed to be related to:

A) getting a lot of SIGABRTs from calling setLoopState (using quicktime). So I modified the loadMovie function to set the loop state to OF_LOOP_NONE at load, which does work.

B)The second problem is that once the movie completes (with OF_LOOP_NONE), none of the stop, play or load commands seem to work anymore. So I’ve switched back to leaving everything at OF_LOOP_NORMAL, and checking for end of movie by checking current frame.

also, If I were to try to use the goVideoPlayer with GStreamer, what OS was it designed for/tested on? Windows? Linux? both?

thanks for your help.

gstreamer is been tested on linux mostly, but if you manage to compile it for windows it should work the same.

btw. it would be super useful if you could create issues for these problems in github

In the past I have used GStreamer in windows (with 0061/62) but I was mostly asking because I think the example goVideoPlayer Codeblocks project was a Windows project file and not Linux, so I wanted to know if the addon itself if designed to use for windows and/or whether or not its safe to use with Linux.

ah ok, i was thinking you were asking the opposite :slight_smile:

after a bit of poking around it looks like the GStreamer code for this addon must be for Linux, but not for 007.
I’m going to take a quick stab at getting it running on 0062, and if that doesn’t work, I’ll let it go and give up.

On the upside, I got the app doing what I need in QuickTime (seamlessly crossfading between a folder of videos), but not with the HD perfomance I need. still, it’s progress…

@Drosen

Yep all the gstreamer code in goVideoPlayer is 0062 :frowning: In fact the whole thing is 0062 with a nasty hack to make it work in 007. Haven’t had time to do a proper update. Sorry about that.

Also I only tested this on Mac and Windows using Quicktime.

I got the app doing what I need in QuickTime (seamlessly crossfading between a folder of videos), but not with the HD perfomance I need

You probably already did this but worth checking: when you load ‘a folder of videos’ do you make sure to call setPause(true) on all of them except the ones you are actually drawing to screen? If not they will be chewing up system resources even if you’re not calling update and draw once they’re loaded. This exact thing bit me once, so thought it was worth mentioning.

I’m only using two GoThreadedVideo objects, one for the current clip, and one for the next clip in line, so I think I’m safe for that. It’s more that the standard quick-time library is getting long in the tooth and just doesn’t perform how I need at a base level. On mac I’ve been using the ofxQtkit video player, which has the performance, but isn’t threaded. I’m hoping that someday in the near future (OF008 maybe?) we can move to a better-performing library as standard across all platforms. Seeing how good GSVideo for Processing is has convinced me that it’s time for a change.

Hi,
Thanks for this great addon gameover! I am using many goThreadedVideo players to load videos in background.
Another quick solution to control the goVideoPlayer::loadMovie calls is to use a static mutex in the treaded function and comment the loading condition in goThreadedVideo::loadMovie.

  
  
static ofMutex LoadMutex;  
//...  
void goThreadedVideo::threadedFunction() {  
  
	// this is where we load the video in a thread  
	// whilst the texture is turned off...  
  
	LoadMutex.lock();  
  
	stopThread();										// immediately stop the thread  
  
	bool ok = video[cueVideo]->loadMovie(name[cueVideo], true);	// load the movie  
	if (ok) {  
		video[cueVideo]->play();							// and start playing it  
		video[cueVideo]->setLoopState(OF_LOOP_NORMAL);  
		loaded[cueVideo] = true;							// set flag that the video is loaded  
	} else {  
		int err = GO_TV_MOVIE_ERROR;  
		ofNotifyEvent(error, err);  
	}  
	  
	LoadMutex.unlock();  
}  
  

i have problems with setLoopState.
no matter what i set it to it always does the normal loop

no -> OF_LOOP_PALINDROME
no -> OF_LOOP_NONE

i tried OF007 and OF 062 on osX
with the normal ofVideoPlayer it works fine.
s.

Although this might be a little off topic, but it was mentioned before: I’m trying to get goThreadedVideo under Linux and OF 007 to work. Instead of updating the goVideoPlayer class to the new gStreamer Code in OF007, I am just changing the goThreadedVideo class so that it is using the standard ofVideoPlayer.

This is done mainly by doing this:

  • Changed the video array in goThreadedVideo.h back to a ofVideoPlayer reference.

  • In goThreadedVideo.cpp removed all the occurances of forceTextureUpload() and added the code directly (which is not very beautiful) in the update and pseudoupdate Function.

That’s the code to switch texturing back on:

  
  
ofTexture & tref = video[cueVideo]->getTextureReference();  
tref.allocate(video[cueVideo]->getWidth(),video[cueVideo]->getHeight(), GL_RGB);  
  

For me, this solution runs perfectly.

Best,
Urs

Update: running ubuntu Oneiric Ocelot…

@hofer: oh cool! so it’s working with of007 that easily? There are a bunch of other changes made to goVideoPlayer for various reasons in the past (which I’d have to hunt down and implement for of007), but great to see this working!

@stephanschulz: I think the problem you’re having is one of precedence. You need to call setLoopState *after* the video has loaded…ie., by watching for a loaded event and then setting the loop state. Does that make sense? Would probably be better if I had some kind of cached value for this…will get to it soon…

Hi Matt.

i am calling setLoopState after loading. I am doing all this in setup()

movie[movieFileCount].loadMovie(fileNameMov); movie[movieFileCount].setLoopState(OF\_LOOP\_PALINDROME);

but it is not looping properly.
i am also noticing that when I am changing the speed once in a while the video freezes for a moment.

s.

@stephanschulz: the reason that is not working is because the video is not actually loaded straight away (that’s the nature of loading on a thread) instead it loads ‘at some point’ on a thread, which is caught in the update and method and then the texture is ‘forced’ to upload and THEN it’s loaded. At that point an event is fired to let you know it’s loaded…otherwise it’s pure guesswork as to when it’s ready…

In the process of adding an example to the repo that demonstrates this I fixed the problem people are facing by caching the the call to setLoopState if the video is not loaded and then applying it once it is actually loaded…

…so although before it wouldn’t work for the reason above…now it should :wink:

You’ll have to check out or pull the new version from the repo…

m

thanks a lot.