From add2b9728202dde95ffe6a5491ff77e6583e5a92 Mon Sep 17 00:00:00 2001 From: Clay Budin Date: Tue, 15 Dec 2015 10:14:38 -0500 Subject: [PATCH 01/10] Added some comments to update(), tested building cinder lib in debug and release --- src/cinder/app/AppBase.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/cinder/app/AppBase.cpp b/src/cinder/app/AppBase.cpp index 4dc36c16c1..dfa8855c3e 100644 --- a/src/cinder/app/AppBase.cpp +++ b/src/cinder/app/AppBase.cpp @@ -155,6 +155,7 @@ void AppBase::privateSetup__() setup(); } +// CB - this is the central update() call in the application void AppBase::privateUpdate__() { mFrameCount++; @@ -170,10 +171,12 @@ void AppBase::privateUpdate__() mSignalUpdate.emit(); - update(); + update(); // call ::update() + // update master timeline - not sure why this is done after update() mTimeline->stepTo( static_cast( getElapsedSeconds() ) ); + // update FPS statistics double now = mTimer.getSeconds(); if( now > mFpsLastSampleTime + mFpsSampleInterval ) { //calculate average Fps over sample interval From c51b782937cf0672e2aadf11a653a4d023da70d3 Mon Sep 17 00:00:00 2001 From: Clay Budin Date: Tue, 15 Dec 2015 14:41:12 -0500 Subject: [PATCH 02/10] Fixed bug with PingPong mode that I've fixed before --- src/cinder/TimelineItem.cpp | 4 +++- src/cinder/app/AppBase.cpp | 1 + 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/cinder/TimelineItem.cpp b/src/cinder/TimelineItem.cpp index 55b352e0f6..df04d374e6 100644 --- a/src/cinder/TimelineItem.cpp +++ b/src/cinder/TimelineItem.cpp @@ -115,7 +115,9 @@ void TimelineItem::stepTo( float newTime, bool reverse ) complete( true ); } } - else if( ( ! mLoop ) && ( ! mInfinite ) ) { // newTime >= endTime + // CB - I've fixed this bug before + //else if( ( ! mLoop ) && ( ! mInfinite ) ) { // newTime >= endTime + else if( ( ! mLoop ) && ( ! mInfinite ) && !mPingPong ) { // newTime >= endTime if( ( ! mComplete ) && ( ! reverse ) ) { mComplete = true; mReverseComplete = false; diff --git a/src/cinder/app/AppBase.cpp b/src/cinder/app/AppBase.cpp index dfa8855c3e..044bb51931 100644 --- a/src/cinder/app/AppBase.cpp +++ b/src/cinder/app/AppBase.cpp @@ -171,6 +171,7 @@ void AppBase::privateUpdate__() mSignalUpdate.emit(); +//CI_LOG_I("update()"); update(); // call ::update() // update master timeline - not sure why this is done after update() From 8462d977b48939f59bec3a613450fecc122ed030 Mon Sep 17 00:00:00 2001 From: Clay Budin Date: Tue, 15 Dec 2015 15:02:12 -0500 Subject: [PATCH 03/10] Experiment - replace mTimer with fixed-step time computed from mFrameCount --- include/cinder/app/AppBase.h | 4 +++- src/cinder/app/AppBase.cpp | 11 +++++++++-- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/include/cinder/app/AppBase.h b/include/cinder/app/AppBase.h index 65116caf56..9db04f7176 100644 --- a/include/cinder/app/AppBase.h +++ b/include/cinder/app/AppBase.h @@ -331,7 +331,9 @@ class AppBase { virtual void setFullScreen( bool fullScreen, const FullScreenOptions &options = FullScreenOptions() ) { getWindow()->setFullScreen( fullScreen, options ); } //! Returns the number of seconds which have elapsed since application launch - double getElapsedSeconds() const { return mTimer.getSeconds(); } + //double getElapsedSeconds() const { return mTimer.getSeconds(); } +// CB +double getElapsedSeconds() const { return mFrameCount / 60.0; } //! Returns the number of animation frames which have elapsed since application launch uint32_t getElapsedFrames() const { return mFrameCount; } diff --git a/src/cinder/app/AppBase.cpp b/src/cinder/app/AppBase.cpp index 044bb51931..3965bd3bf7 100644 --- a/src/cinder/app/AppBase.cpp +++ b/src/cinder/app/AppBase.cpp @@ -173,12 +173,19 @@ void AppBase::privateUpdate__() //CI_LOG_I("update()"); update(); // call ::update() + +// CB +// mTimer is used only here and in getElapsedSeconds() +//double now = mTimer.getSeconds(); +double now = mFrameCount / 60.0; // update master timeline - not sure why this is done after update() - mTimeline->stepTo( static_cast( getElapsedSeconds() ) ); + //mTimeline->stepTo( static_cast( getElapsedSeconds() ) ); + mTimeline->stepTo( static_cast( now ) ); // update FPS statistics - double now = mTimer.getSeconds(); + // mFpsSampleInterval == 1 by default + //double now = mTimer.getSeconds(); if( now > mFpsLastSampleTime + mFpsSampleInterval ) { //calculate average Fps over sample interval uint32_t framesPassed = mFrameCount - mFpsLastSampleFrame; From 5ed79380902591f96495c33595d1ee279ae3a363 Mon Sep 17 00:00:00 2001 From: Clay Budin Date: Tue, 15 Dec 2015 15:23:40 -0500 Subject: [PATCH 04/10] Use frame rate as set by application for base step time --- include/cinder/app/AppBase.h | 3 ++- src/cinder/app/AppBase.cpp | 4 +++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/include/cinder/app/AppBase.h b/include/cinder/app/AppBase.h index 9db04f7176..75ea63ba5a 100644 --- a/include/cinder/app/AppBase.h +++ b/include/cinder/app/AppBase.h @@ -333,7 +333,8 @@ class AppBase { //! Returns the number of seconds which have elapsed since application launch //double getElapsedSeconds() const { return mTimer.getSeconds(); } // CB -double getElapsedSeconds() const { return mFrameCount / 60.0; } +//double getElapsedSeconds() const { return mFrameCount / 60.0; } +double getElapsedSeconds() const { return mFrameCount / getFrameRate(); } //! Returns the number of animation frames which have elapsed since application launch uint32_t getElapsedFrames() const { return mFrameCount; } diff --git a/src/cinder/app/AppBase.cpp b/src/cinder/app/AppBase.cpp index 3965bd3bf7..5b63839066 100644 --- a/src/cinder/app/AppBase.cpp +++ b/src/cinder/app/AppBase.cpp @@ -176,8 +176,10 @@ void AppBase::privateUpdate__() // CB // mTimer is used only here and in getElapsedSeconds() +// mFrameRate defaults to 60.0f, used in startAnimationTimer() to create a timer which fires at the frame rate //double now = mTimer.getSeconds(); -double now = mFrameCount / 60.0; +//double now = mFrameCount / 60.0; +double now = mFrameCount / getFrameRate(); // update master timeline - not sure why this is done after update() //mTimeline->stepTo( static_cast( getElapsedSeconds() ) ); From fe0aee56bcc0b7327dd04fdb643c09a5fa768842 Mon Sep 17 00:00:00 2001 From: Clay Budin Date: Tue, 15 Dec 2015 17:15:25 -0500 Subject: [PATCH 05/10] Modify QT movie to take multiple steps forwards with single call --- include/cinder/qtime/QuickTimeImplAvf.h | 4 ++-- src/cinder/qtime/QuickTimeImplAvf.mm | 10 ++++++---- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/include/cinder/qtime/QuickTimeImplAvf.h b/include/cinder/qtime/QuickTimeImplAvf.h index 5fe2b3186e..53c2b6dbef 100644 --- a/include/cinder/qtime/QuickTimeImplAvf.h +++ b/include/cinder/qtime/QuickTimeImplAvf.h @@ -127,9 +127,9 @@ class MovieBase { //! Sets whether the movie is set to loop during playback. If \a palindrome is true, the movie will "ping-pong" back and forth void setLoop( bool loop = true, bool palindrome = false ); //! Advances the movie by one frame (a single video sample). Ignores looping settings. - bool stepForward(); + bool stepForward( int frms = 1 ); //! Steps backward by one frame (a single video sample). Ignores looping settings. - bool stepBackward(); + bool stepBackward( int frms = 1 ); /** Sets the playback rate, which begins playback immediately for nonzero values. * 1.0 represents normal speed. Negative values indicate reverse playback and \c 0 stops. * diff --git a/src/cinder/qtime/QuickTimeImplAvf.mm b/src/cinder/qtime/QuickTimeImplAvf.mm index d67922ec7e..74c8af6e1c 100644 --- a/src/cinder/qtime/QuickTimeImplAvf.mm +++ b/src/cinder/qtime/QuickTimeImplAvf.mm @@ -367,20 +367,21 @@ - (void)outputSequenceWasFlushed:(AVPlayerItemOutput *)output mPalindrome = (loop? palindrome: false); } -bool MovieBase::stepForward() +bool MovieBase::stepForward( int frms /* = 1 */ ) { if( ! mPlayerItem ) return false; bool can_step_forwards = [mPlayerItem canStepForward]; if( can_step_forwards ) { - [mPlayerItem stepByCount:1]; + //[mPlayerItem stepByCount:1]; + [mPlayerItem stepByCount:frms]; } return can_step_forwards; } -bool MovieBase::stepBackward() +bool MovieBase::stepBackward( int frms /* = 1 */ ) { if( ! mPlayerItem) return false; @@ -388,7 +389,8 @@ - (void)outputSequenceWasFlushed:(AVPlayerItemOutput *)output bool can_step_backwards = [mPlayerItem canStepBackward]; if (can_step_backwards) { - [mPlayerItem stepByCount:-1]; + //[mPlayerItem stepByCount:-1]; + [mPlayerItem stepByCount:-frms]; } return can_step_backwards; From 946430ef87575f5db7dd325c83f3b42486d6404f Mon Sep 17 00:00:00 2001 From: Clay Budin Date: Thu, 17 Dec 2015 15:00:18 -0500 Subject: [PATCH 06/10] Added new command setPlaybackForCapture() to toggle between normal time-based playback and frame-locked playback --- include/cinder/app/AppBase.h | 14 +++++++++++--- src/cinder/TimelineItem.cpp | 2 +- src/cinder/app/AppBase.cpp | 16 +++++----------- 3 files changed, 17 insertions(+), 15 deletions(-) diff --git a/include/cinder/app/AppBase.h b/include/cinder/app/AppBase.h index 75ea63ba5a..82769a1555 100644 --- a/include/cinder/app/AppBase.h +++ b/include/cinder/app/AppBase.h @@ -332,11 +332,17 @@ class AppBase { //! Returns the number of seconds which have elapsed since application launch //double getElapsedSeconds() const { return mTimer.getSeconds(); } -// CB -//double getElapsedSeconds() const { return mFrameCount / 60.0; } -double getElapsedSeconds() const { return mFrameCount / getFrameRate(); } + double getElapsedSeconds() const { + return mDoPlaybackForCapture ? mFrameCount / getFrameRate() : mTimer.getSeconds(); + } //! Returns the number of animation frames which have elapsed since application launch uint32_t getElapsedFrames() const { return mFrameCount; } + + void setPlaybackForCapture ( bool doPlaybackForCapture ) { + mDoPlaybackForCapture = doPlaybackForCapture; + mFpsLastSampleTime = getElapsedSeconds(); + mFpsLastSampleFrame = mFrameCount; + } //! Returns whether the app is registered to receive multiTouch events from the operating system, configurable via Settings at startup. Disabled by default on desktop platforms, enabled on mobile. bool isMultiTouchEnabled() const { return mMultiTouchEnabled; } @@ -441,6 +447,8 @@ double getElapsedSeconds() const { return mFrameCount / getFrameRate(); } double mFpsSampleInterval; bool mMultiTouchEnabled, mHighDensityDisplayEnabled; RendererRef mDefaultRenderer; + + bool mDoPlaybackForCapture; std::vector mCommandLineArgs; std::shared_ptr mTimeline; diff --git a/src/cinder/TimelineItem.cpp b/src/cinder/TimelineItem.cpp index df04d374e6..8a9e630e69 100644 --- a/src/cinder/TimelineItem.cpp +++ b/src/cinder/TimelineItem.cpp @@ -117,7 +117,7 @@ void TimelineItem::stepTo( float newTime, bool reverse ) } // CB - I've fixed this bug before //else if( ( ! mLoop ) && ( ! mInfinite ) ) { // newTime >= endTime - else if( ( ! mLoop ) && ( ! mInfinite ) && !mPingPong ) { // newTime >= endTime + else if( ( ! mLoop ) && ( ! mInfinite ) && ( ! mPingPong ) ) { // newTime >= endTime if( ( ! mComplete ) && ( ! reverse ) ) { mComplete = true; mReverseComplete = false; diff --git a/src/cinder/app/AppBase.cpp b/src/cinder/app/AppBase.cpp index 5b63839066..4a994b8aa6 100644 --- a/src/cinder/app/AppBase.cpp +++ b/src/cinder/app/AppBase.cpp @@ -92,7 +92,7 @@ void AppBase::Settings::setShouldQuit( bool shouldQuit ) AppBase::AppBase() : mFrameCount( 0 ), mAverageFps( 0 ), mFpsSampleInterval( 1 ), mTimer( true ), mTimeline( Timeline::create() ), - mFpsLastSampleFrame( 0 ), mFpsLastSampleTime( 0 ) + mFpsLastSampleFrame( 0 ), mFpsLastSampleTime( 0 ), mDoPlaybackForCapture( false ) { sInstance = this; @@ -171,28 +171,22 @@ void AppBase::privateUpdate__() mSignalUpdate.emit(); -//CI_LOG_I("update()"); + //CI_LOG_I("update()"); update(); // call ::update() -// CB -// mTimer is used only here and in getElapsedSeconds() -// mFrameRate defaults to 60.0f, used in startAnimationTimer() to create a timer which fires at the frame rate -//double now = mTimer.getSeconds(); -//double now = mFrameCount / 60.0; -double now = mFrameCount / getFrameRate(); + // mTimer is used only here and in getElapsedSeconds() + // mFrameRate defaults to 60.0f, used in startAnimationTimer() to create a timer which fires at the frame rate + double now = getElapsedSeconds(); // update master timeline - not sure why this is done after update() - //mTimeline->stepTo( static_cast( getElapsedSeconds() ) ); mTimeline->stepTo( static_cast( now ) ); // update FPS statistics // mFpsSampleInterval == 1 by default - //double now = mTimer.getSeconds(); if( now > mFpsLastSampleTime + mFpsSampleInterval ) { //calculate average Fps over sample interval uint32_t framesPassed = mFrameCount - mFpsLastSampleFrame; mAverageFps = (float)(framesPassed / (now - mFpsLastSampleTime)); - mFpsLastSampleTime = now; mFpsLastSampleFrame = mFrameCount; } From d959fa66719c2fea9abab9f81e5e69273ea0cdd3 Mon Sep 17 00:00:00 2001 From: Clay Budin Date: Thu, 17 Dec 2015 15:28:23 -0500 Subject: [PATCH 07/10] Added function getTrueElapsedSeconds() to gain access to time when in capture mode --- include/cinder/app/AppBase.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/cinder/app/AppBase.h b/include/cinder/app/AppBase.h index 82769a1555..b214970db3 100644 --- a/include/cinder/app/AppBase.h +++ b/include/cinder/app/AppBase.h @@ -332,6 +332,7 @@ class AppBase { //! Returns the number of seconds which have elapsed since application launch //double getElapsedSeconds() const { return mTimer.getSeconds(); } + double getTrueElapsedSeconds() const { return mTimer.getSeconds(); } double getElapsedSeconds() const { return mDoPlaybackForCapture ? mFrameCount / getFrameRate() : mTimer.getSeconds(); } From 406ef555f32d9c7b29b10493a595e687ab2366a3 Mon Sep 17 00:00:00 2001 From: Clay Budin Date: Fri, 18 Dec 2015 10:28:29 -0500 Subject: [PATCH 08/10] Added separate frame rate control for catpure playback - controlled via get/setCaptureFrameRate() --- include/cinder/app/AppBase.h | 5 ++++- src/cinder/app/AppBase.cpp | 9 +++++---- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/include/cinder/app/AppBase.h b/include/cinder/app/AppBase.h index b214970db3..61e8f908f5 100644 --- a/include/cinder/app/AppBase.h +++ b/include/cinder/app/AppBase.h @@ -334,7 +334,7 @@ class AppBase { //double getElapsedSeconds() const { return mTimer.getSeconds(); } double getTrueElapsedSeconds() const { return mTimer.getSeconds(); } double getElapsedSeconds() const { - return mDoPlaybackForCapture ? mFrameCount / getFrameRate() : mTimer.getSeconds(); + return mDoPlaybackForCapture ? mFrameCount / mCaptureFrameRate : mTimer.getSeconds(); } //! Returns the number of animation frames which have elapsed since application launch uint32_t getElapsedFrames() const { return mFrameCount; } @@ -344,6 +344,8 @@ class AppBase { mFpsLastSampleTime = getElapsedSeconds(); mFpsLastSampleFrame = mFrameCount; } + float getCaptureFrameRate() const { return mCaptureFrameRate; } + void setCaptureFrameRate( float frameRate ) { mCaptureFrameRate = frameRate; } //! Returns whether the app is registered to receive multiTouch events from the operating system, configurable via Settings at startup. Disabled by default on desktop platforms, enabled on mobile. bool isMultiTouchEnabled() const { return mMultiTouchEnabled; } @@ -450,6 +452,7 @@ class AppBase { RendererRef mDefaultRenderer; bool mDoPlaybackForCapture; + float mCaptureFrameRate; std::vector mCommandLineArgs; std::shared_ptr mTimeline; diff --git a/src/cinder/app/AppBase.cpp b/src/cinder/app/AppBase.cpp index 4a994b8aa6..45c8d12d84 100644 --- a/src/cinder/app/AppBase.cpp +++ b/src/cinder/app/AppBase.cpp @@ -92,7 +92,8 @@ void AppBase::Settings::setShouldQuit( bool shouldQuit ) AppBase::AppBase() : mFrameCount( 0 ), mAverageFps( 0 ), mFpsSampleInterval( 1 ), mTimer( true ), mTimeline( Timeline::create() ), - mFpsLastSampleFrame( 0 ), mFpsLastSampleTime( 0 ), mDoPlaybackForCapture( false ) + mFpsLastSampleFrame( 0 ), mFpsLastSampleTime( 0 ), + mDoPlaybackForCapture( false ), mCaptureFrameRate( 30 ) { sInstance = this; @@ -155,7 +156,7 @@ void AppBase::privateSetup__() setup(); } -// CB - this is the central update() call in the application +// this is the central update() call in the application void AppBase::privateUpdate__() { mFrameCount++; @@ -171,18 +172,18 @@ void AppBase::privateUpdate__() mSignalUpdate.emit(); - //CI_LOG_I("update()"); update(); // call ::update() // mTimer is used only here and in getElapsedSeconds() // mFrameRate defaults to 60.0f, used in startAnimationTimer() to create a timer which fires at the frame rate + // mCaptureFrameRate defaults to 30.0f since that's what works best for quicktime videos double now = getElapsedSeconds(); // update master timeline - not sure why this is done after update() mTimeline->stepTo( static_cast( now ) ); // update FPS statistics - // mFpsSampleInterval == 1 by default + // mFpsSampleInterval == 1.0 secs by default if( now > mFpsLastSampleTime + mFpsSampleInterval ) { //calculate average Fps over sample interval uint32_t framesPassed = mFrameCount - mFpsLastSampleFrame; From 7d40db5d02e017341af2461a9a3edaf5c0b902cb Mon Sep 17 00:00:00 2001 From: Clay Budin Date: Wed, 23 Dec 2015 12:51:02 -0500 Subject: [PATCH 09/10] Added function getPlaybackFrameRate() to retrieve current playback fps - either real-time or capture --- include/cinder/app/AppBase.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/include/cinder/app/AppBase.h b/include/cinder/app/AppBase.h index 61e8f908f5..41555d5465 100644 --- a/include/cinder/app/AppBase.h +++ b/include/cinder/app/AppBase.h @@ -346,6 +346,10 @@ class AppBase { } float getCaptureFrameRate() const { return mCaptureFrameRate; } void setCaptureFrameRate( float frameRate ) { mCaptureFrameRate = frameRate; } + + float getPlaybackFrameRate() const { + return mDoPlaybackForCapture ? mCaptureFrameRate : getFrameRate(); + } //! Returns whether the app is registered to receive multiTouch events from the operating system, configurable via Settings at startup. Disabled by default on desktop platforms, enabled on mobile. bool isMultiTouchEnabled() const { return mMultiTouchEnabled; } From c1001245fdcc31ab8d09cd91b89d722856d50ff5 Mon Sep 17 00:00:00 2001 From: Clay Budin Date: Wed, 23 Dec 2015 13:07:23 -0500 Subject: [PATCH 10/10] Added global accessor for getPlaybackFrameRate() function --- include/cinder/app/AppBase.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/include/cinder/app/AppBase.h b/include/cinder/app/AppBase.h index 41555d5465..892e9bcfe6 100644 --- a/include/cinder/app/AppBase.h +++ b/include/cinder/app/AppBase.h @@ -514,6 +514,8 @@ inline Area getWindowBounds() { return AppBase::get()->getWindowBounds(); } inline float getWindowContentScale() { return AppBase::get()->getWindowContentScale(); } //! Returns the maximum frame-rate the active App will attempt to maintain. inline float getFrameRate() { return AppBase::get()->getFrameRate(); } +//! Returns the current frame rate setting - either real-time or capture mode +inline float getPlaybackFrameRate() { return AppBase::get()->getPlaybackFrameRate(); } //! Sets the maximum frame-rate the active App will attempt to maintain. inline void setFrameRate( float frameRate ) { AppBase::get()->setFrameRate( frameRate ); } //! Returns whether the active App is in full-screen mode or not.