ofVideoPlayer shows black frame sometimes when loading


#1
// .h
class ofApp : public ofBaseApp {
    public:
        void setup();
        void update();
        void draw();
        void keyPressed(int key);
        ofVideoPlayer vid;
        int id {1};
};
// .cpp
void ofApp::setup() {
    ofSetBackgroundColor(255);
}

void ofApp::update() {
    if(vid.isLoaded()) {
        vid.update();
    }
}

void ofApp::draw() {
    if(vid.isLoaded() && vid.getCurrentFrame() >= 0) {
        vid.draw(0, 0, 400, 200);
    }
}

void ofApp::keyPressed(int) {
    // vid.close(); // stops working
    vid.loadAsync("/path/tut" + ofToString(1 + (++id % 7)) + ".mp4");
    vid.play();
    vid.setLoopState(ofLoopType::OF_LOOP_NORMAL);
}

Why can it be that while loading a video a black frame is flashed during one frame? I tried checking if the video is loaded, allocated, the frame not being -1 (sometimes it is), but none of the tests help with this.

Mmm… by looking at the gst code, it seems like bLoaded is never set to false, unless you close() it. But if you do then you can’t load other movies. Wouldn’t it make sense to set it to false when starting to load, and to true when loaded? Or what’s the right approach to switch movies?


#2

I think this is related to using loadAsync. isLoaded returns true after you’ve called load or loadAsync succesfully but in the case of loadAsync it might not have finished actually loading the content. I don’t think we can change isLoaded’s behaviour without breaking old code in weird ways that are difficult to detect but we could add a second method that let’s you know if loadAsync has actually finished loading in the background


#3

You’re right, without async it doesn’t flicker. The issue is that on iOS it’s always async. I can try do what you suggest see if that solves it. Maybe vid.isLoadedAsync().


#4

yes if you want to take a look i think that would be useful. Not sure about the name, isLoadedAsync is kind of confusing but we can change it later if we figure out something better. Be aware that video uses 5 different apis depending on the platform so we would need to implement this for every platform at least the ones that implement loadAsync, i think android and probably windows don’t.

If ios always loads asynchronously that’s also something we have to take into account. if you don’t load using async but then have to call loadAsync to really check the video is loaded is even more confusing


#5

Unfortunately that’s more work than I can invest now.

I know my videos have white background so this ugly hack seems to avoid the black frames:

void ofApp::draw() {
    if(vid.getPixels().isAllocated() && vid.getCurrentFrame() >= 0) {
        if(vid.getPixels().getData()[0] > 0) { // skip frame if data == 0
            vid.draw(0, 0);
        }
    }
}

This code doesn’t count for my next job application :stuck_out_tongue: