Thread Lock with ofVideoPlayer (ofQTKitPlayer)

It looks to me like ofVideoPlayer needs a little help avoiding a deadlock when stopping and closing a video file. I have found that if you repeatedly load/close an ofVideoPlayer, eventually the video QTKit underpinnings arrive at a deadlock where QTKit is trying to run the video texture update function (QTVisualContextImageAvailableCallback) at the same time as it is trying to reassign/clear the texture update function with QTVisualContextSetImageAvailableCallback.

I created a spin-off of the standard ofVideoPlayer example to illustrate the issue (which can be found at https://github.com/BenVanCitters/PathologicalVideoLoad). It looks like not many other people have encountered this issue. I am running on OSX 10.8.5 with Xcode 5 and OF 0.8.0.

It looks like calling ofVideoPlayer.stop() fixes the issue provided that you give it enough time to complete any related callbacks.

Is there a better way to handle this? Am I wrong about the thread dead-lock?

1 Like

Is this related?

Yeah, that looks basically like the same stack trace as I have seen in the hangs. It could be the same issue. The repro steps for me are

  1. Create an ofVideoPlayer
  2. Load a movie file
  3. Close the ofVideoPlayer.
  4. Repeat until a hang occurs.

The Dealloc method of ofQTKitMovieRenderer is responsible for the hang as far as I know.

I am not sure how closely related this is, but I am experiencing the ofVideoPlayer hanging on a frame as well - it doesn’t advance. If I drill down in the debugger into ofQTKitPlayer, I hit QTKitMovieRenderer.m’s update() and it doesn’t seem to think the frame is new for some reason. This happens after many loops (i.e stop() and position = 0) of the movie .

Hey I know this is an old thread, but I just had this same problem and I just wanted to confirm that @BenVanCitters’s solution fixed it for me. Basically OF eventually hangs when you try to open and close a bunch of ofVideoPlayer objects. Calling stop(), then update(), then sleeping for 100 milliseconds before calling close() did the trick. Not sure if the sleep is actually necessary, I’m gonna test that out.

This is the code (there might be some unnecessary lines in there from trying other possible solutions that I’d found):

movieLoaded = false;  // this is to stop it from trying to update or play a movie if it hasn't loaded yet
myVideo->stop();
myVideo->update();
ofSleepMillis(100);
myVideo->closeMovie();
delete myVideo;
myVideo = new ofVideoPlayer;
myVideo->loadMovie(_videoPath);
myVideo->play();
myVideo->setSpeed(1);
myVideo->setLoopState(OF_LOOP_NORMAL);
movieLoaded = true;

EDIT: Yes sleeping is necessary. I reduced it to 50ms with no problem.