Black pixels when looping through video loaded by Direct Show Player

Hi, in the past (OF 0.8.x) I used code like this to load video frames into a vector<ofPixels>:

video.loadMovie("myMovie.mov");
video.setFrame(0);

int numFrames = video.getTotalNumFrames();
myBuffer.resize(numFrames);

for (int i = 0; i < numFrames; ++i){
    myBuffer[i] = video.getPixelsRef();
    video.nextFrame();
}

For some reason this doesn’t work anymore with Direct Show Player (Win 7, OF 0.9.3). The dimensions of the pixels are right, but they are all black!
On Quicktime, calling setFrame() would load the frame, but Direct Show won’t do that! Calling update() after setFrame() won’t work as well…

Of course I could use another video player, but the functionality is part of an addon I’m working on and I’d rather like to use the standard ofVideoPlayer to keep it as generic as possible…

Any ideas?

Christof

Not sure if this is the same issue but for it was the version of codec pack

https://github.com/openframeworks/openFrameworks/issues/5114

I still get “unable to call GetConnectedMediaType” with Direct Show on some mp4s, although most of the time it works. I got the latest KLite Codec Pack from ninite, by the way.

Regarding my issue, I think I found the problem.
First, if I do this:

video.loadMovie("myMovie.mov");
video.play();
video.setFrame(0);

then DS starts to actually load pixels from the video file. Calling play() was not necessary with Quicktime!

The bad news: setFrame() seems to happen totally asynchronous, no matter what I try, I can’t make the for loop wait for an actual new frame being loaded. playing around with isFrameNew() doesn’t help either…

I’m currently loading 1000 frames but the resulting pixels only show the first 10-11 frames (since it’s not deterministic, it’s got something to do with threads), spread over 1000 frames (so lots of repetitions of a single frame).

So what seems to happen is this:
setFrame() asks to get a new frame from the video, but it’s somehow threaded, so the for loop continues and keeps writing old video pixels into the buffer until DS has actually loaded the new frame.

This behaviour is very different from ofVideoPlayer in OF 0.8.x and I’m wondering if it only happens with DS or also with the other new video players on MacOS and Linux.

But the more important question: how can I get the for loop to wait for a new frame being loaded by DS? Using isFrameNew() and getCurrentFrame() inside the for-loop seems to block ofVideoPlayer from loading a new frame at all (and the resulting vector is 1000x the first frame).

Any help or comments are highly appreciated!

I love OF 0.9.x but I’m getting more and more frustrated with DS… (there are also problems playing files encoded with motion JPEG. it would only show the first frame and then hang itself… but that’s another story)

Christof

Ok, finally got it working:

        video.load("foo.mov");
        video.setSpeed(0);
        video.play();
        video.setFrame(0);
        int numFrames = video.getTotalNumFrames();
        myBuffer.resize(numFrames);

        for (int i = 0; i < numFrames; ++i){
            while (true){
                video.update();
                if (video.isFrameNew()){
                    cout << "new frame: " << video.getCurrentFrame() << "!\n";
                    break;
                }
            }
            cout << "loop index: " << i << "\n";
            myBuffer[i] = video.getPixels();
            video.nextFrame();
        }

Basically it works, but there are still two problems:

  1. sometimes the frame index lags behind for 1-2 frames (0, 0, 0, 1, 2, 3, 4 …)
  2. it’s horribly slow - slower than realtime! Quicktime, however, was much faster than realtime (probably because you didn’t need to call play() and update()).

I’m actually pretty confused how setFrame(), getCurrentFrame(), isFrameNew() and update() relate to each other in ofDirectShowPlayer…