//-------------------------------------------------------------- void ofxThreadedVideo::setVolume(int _volume){ Poco::ScopedLock<ofMutex> lock(); if(currentVideoID != VIDEO_NONE && loadVideoID == VIDEO_NONE){ volume[currentVideoID] = _volume; videos[currentVideoID].setVolume(volume[currentVideoID]); } volume[getNextLoadID()] = _volume; videos[getNextLoadID()].setVolume(volume[getNextLoadID()]); }
//-------------------------------------------------------------- void ofxThreadedVideo::setPaused(bool b){ Poco::ScopedLock<ofMutex> lock(); if(currentVideoID != VIDEO_NONE && loadVideoID == VIDEO_NONE){ bPaused[currentVideoID] = b; } bPaused[getNextLoadID()] = b; }
//-------------------------------------------------------------- void ofxThreadedVideo::setFrame(int frame){ Poco::ScopedLock<ofMutex> lock(); if(currentVideoID != VIDEO_NONE && loadVideoID == VIDEO_NONE){ newFrame[currentVideoID] = frame; } newFrame[getNextLoadID()] = frame; }
//-------------------------------------------------------------- void ofxThreadedVideo::setSpeed(float speed){ Poco::ScopedLock<ofMutex> lock(); if(currentVideoID != VIDEO_NONE && loadVideoID == VIDEO_NONE){ newSpeed[currentVideoID] = speed; } newSpeed[getNextLoadID()] = speed; }
//-------------------------------------------------------------- void ofxThreadedVideo::setLoopState(ofLoopType state){ Poco::ScopedLock<ofMutex> lock(); if(currentVideoID != VIDEO_NONE && loadVideoID == VIDEO_NONE){ newLoopType[currentVideoID] = state; } newLoopType[getNextLoadID()] = state; }
//-------------------------------------------------------------- void ofxThreadedVideo::setPosition(float pct){ Poco::ScopedLock<ofMutex> lock(); CLAMP(pct, 0.0f, 1.0f); if(currentVideoID != VIDEO_NONE && loadVideoID == VIDEO_NONE){ newPosition[currentVideoID] = pct; } newPosition[getNextLoadID()] = pct; }
//-------------------------------------------------------------- void ofxThreadedVideo::update(){ lock(); if(!bCriticalSection && bLoaded){ bCriticalSection = true; int videoID = currentVideoID; bool bUpdate = bLoaded; unlock(); if(bUpdate){ // lock(); video[videoID].update(); bIsFrameNew = video[videoID].isFrameNew(); position = video[videoID].getPosition(); frameCurrent = video[videoID].getCurrentFrame(); bIsMovieDone = video[videoID].getIsMovieDone(); // unlock(); if(bIsFrameNew || bForceFrameNew){ if(bForceFrameNew) lock(); if(!bIsTextureReady) bIsTextureReady = true; if(drawTexture.getWidth() != width || drawTexture.getHeight() != height){ drawTexture.allocate(width, height, ofGetGLTypeFromPixelFormat(video[videoID].getPixelFormat())); } unsigned char * pixels = video[videoID].getPixels(); if(pixels != NULL && bUseTexture) drawTexture.loadData(pixels, width, height, ofGetGLTypeFromPixelFormat(video[videoID].getPixelFormat())); if(bForceFrameNew){ bForceFrameNew = false; unlock(); } // calculate frameRate -> taken from ofAppRunner prevMillis = ofGetElapsedTimeMillis(); timeNow = ofGetElapsedTimef(); double diff = timeNow-timeThen; if( diff > 0.00001 ){ fps = 1.0 / diff; frameRate *= 0.9f; frameRate += 0.1f*fps; } lastFrameTime = diff; timeThen = timeNow; } } lock(); bCriticalSection = false; unlock(); }else{ unlock(); } lock(); ofxThreadedVideoGlobalMutex.lock(); if(!ofxThreadedVideoGlobalCritical && !bCriticalSection){ int videoID = currentVideoID; ofxThreadedVideoGlobalCritical = true; bCriticalSection = true; ofxThreadedVideoCommand c = getCommand(); bool bCanStop = (bLoaded && !bIsLoading) || (!bLoaded && !bIsLoading); bool bPopCommand = false; unlock(); ofxThreadedVideoGlobalMutex.unlock(); if(c.getInstance() == instanceID){ if(c.getCommand() == "stop" && bCanStop){ if(bVerbose) ofLogVerbose() << instanceID << " = " << c.getCommandAsString(); if(bIsPlaying) video[videoID].stop(); lock(); //fade = 1.0; fades.clear(); bIsPlaying = false; bIsPaused = false; // ???? bIsLoading = false; bIsFrameNew = false; bIsMovieDone = false; bLoaded = false; unlock(); bPopCommand = true; } if(c.getCommand() == "loadMovie" && bCanStop){ if(bVerbose) ofLogVerbose() << instanceID << " = " << c.getCommandAsString() << " execute in update"; if(bIsPlaying) video[videoID].stop(); lock(); currentVideoID = getNextLoadID(); bIsPaused = false; bLoaded = false; bIsLoading = true; bIsPlaying = false; bIsMovieDone = false; unlock(); } if(c.getCommand() == "setSpeed"){ if(bVerbose) ofLogVerbose() << instanceID << " = " << c.getCommandAsString(); lock(); speed = c.getArgument<float>(0); unlock(); video[videoID].setSpeed(speed); bPopCommand = true; } if(c.getCommand() == "setFrame"){ if(bVerbose) ofLogVerbose() << instanceID << " = " << c.getCommandAsString(); lock(); int frameTarget = c.getArgument<int>(0); bForceFrameNew = true; frameTarget = CLAMP(frameTarget, 0, frameTotal); //cout << "setframe A: " << frameTarget << " " << videoID << " " << bCriticalSection << endl; video[videoID].setFrame(frameTarget); //cout << "setframe B: " << frameTarget << " " << videoID << " " << bCriticalSection << endl; unlock(); bPopCommand = true; } } lock(); ofxThreadedVideoGlobalMutex.lock(); if(bPopCommand) popCommand(); ofxThreadedVideoGlobalCritical = false; bCriticalSection = false; ofxThreadedVideoGlobalMutex.unlock(); unlock(); }else{ ofxThreadedVideoGlobalMutex.unlock(); unlock(); } }
//-------------------------------------------------------------- void ofxThreadedVideo::threadedFunction(){ while (isThreadRunning()){ if(lock()){ // if there's a movie to load... if(loadPath != ""){ loadVideoID = getNextLoadID(); paths[loadVideoID] = loadPath; loadPath = ""; #ifdef TARGET_OSX vector<string> pathParts = ofSplitString(paths[loadVideoID], "/"); #else vector<string> pathParts = ofSplitString(paths[loadVideoID], "\\"); #endif names[loadVideoID] = pathParts[pathParts.size() - 1]; // using a static mutex blocks all threads (including the main app) until we've loaded ofxThreadedVideoMutex.lock(); // load that movie! if(videos[loadVideoID].loadMovie(paths[loadVideoID])){ ofLogVerbose() << "Loaded" << names[loadVideoID] << " " << loadVideoID; // start rolling if AutoPlay is true if (bUseAutoPlay) videos[loadVideoID].play(); // set pixel refs pixels[loadVideoID] = &videos[loadVideoID].getPixelsRef(); }else{ ofLogVerbose() << "Could not load video"; loadVideoID = VIDEO_NONE; // send event notification ofxThreadedVideoEvent videoEvent = ofxThreadedVideoEvent(paths[loadVideoID], VIDEO_EVENT_LOAD_FAIL, this); ofNotifyEvent(threadedVideoEvent, videoEvent, this); } ofxThreadedVideoMutex.unlock(); } // do threaded update of videos updateVideo(currentVideoID); updateVideo(loadVideoID); unlock(); // sleep a bit so we don't thrash the cores!! ofSleepMillis(1000/30); // TODO: implement target frame rate? US might need 30 here? } } }