Krita Source Code Documentation
Loading...
Searching...
No Matches
KisPlaybackEngineQT Class Reference

The KisPlaybackEngineQT class is an implementation of KisPlaybackEngine that drives animation playback using simple Qt functionality alone. More...

#include <KisPlaybackEngineQT.h>

+ Inheritance diagram for KisPlaybackEngineQT:

Classes

struct  Private
 

Public Member Functions

boost::optional< int64_t > activeFramesPerSecond () const
 
bool isMute () override
 
 KisPlaybackEngineQT (QObject *parent=nullptr)
 
PlaybackStats playbackStatistics () const override
 
void seek (int frameIndex, SeekOptionFlags flags=SEEK_FINALIZE|SEEK_PUSH_AUDIO) override
 
void setDropFramesMode (bool value) override
 
void setMute (bool) override
 
bool supportsAudio () override
 
bool supportsVariablePlaybackSpeed () override
 
 ~KisPlaybackEngineQT ()
 
- Public Member Functions inherited from KisPlaybackEngine
 KisPlaybackEngine (QObject *parent=nullptr)
 
 ~KisPlaybackEngine ()
 
- Public Member Functions inherited from KoCanvasObserverBase
 KoCanvasObserverBase ()
 
KoCanvasBaseobservedCanvas () const
 
virtual QString observerName ()
 
void setObservedCanvas (KoCanvasBase *canvas)
 
void unsetObservedCanvas ()
 
virtual ~KoCanvasObserverBase ()
 

Protected Slots

void throttledDriverCallback ()
 throttledDriverCallback handles signals from the internal driver that drives playback within this engine. It will either increment frame time, wrapping within bounds, and communicate with KisFrameDisplayProxy or use the driver's desired time to control which frame is visible...
 
- Protected Slots inherited from KisPlaybackEngine

Protected Member Functions

void setCanvas (KoCanvasBase *canvas) override
 
void unsetCanvas () override
 
- Protected Member Functions inherited from KisPlaybackEngine
class KisCanvas2activeCanvas () const
 
int frameWrap (int frame, int startFrame, int endFrame)
 

Private Attributes

QScopedPointer< Privatem_d
 

Additional Inherited Members

- Public Slots inherited from KisPlaybackEngine
bool dropFrames () const
 
virtual void firstFrame ()
 
virtual void lastFrame ()
 
virtual void nextFrame ()
 
virtual void nextKeyframe ()
 
virtual void nextMatchingKeyframe ()
 
virtual void nextUnfilteredKeyframe ()
 
virtual void pause ()
 
virtual void play ()
 
virtual void playPause ()
 
virtual void previousFrame ()
 
virtual void previousKeyframe ()
 
virtual void previousMatchingKeyframe ()
 previousMatchingKeyframe && nextMatchingKeyframe Navigate to the next keyframe that has the same color-label as the current keyframe. Useful to quickly navigate to user-specified 'similar' keyframes. E.g. Contact points in an animation might have a specific color to specify importance and be quickly swapped between.
 
virtual void previousUnfilteredKeyframe ()
 previousUnfilteredKeyframe && nextUnfilteredKeyframe Navigate to keyframes based on the current onion skin filtration. This lets users easily navigate to the next visible "onion-skinned" keyframe on the active layer.
 
virtual void stop ()
 
- Signals inherited from KisPlaybackEngine
void sigDropFramesModeChanged (bool value)
 

Detailed Description

The KisPlaybackEngineQT class is an implementation of KisPlaybackEngine that drives animation playback using simple Qt functionality alone.

As of right now, this playback engine is used as a fallback for when KisPlaybackEngineMLT is unavailable, invalid, or otherwise unwanted.

Definition at line 27 of file KisPlaybackEngineQT.h.

Constructor & Destructor Documentation

◆ KisPlaybackEngineQT()

KisPlaybackEngineQT::KisPlaybackEngineQT ( QObject * parent = nullptr)
explicit

Definition at line 167 of file KisPlaybackEngineQT.cpp.

168 : KisPlaybackEngine(parent)
169 , m_d(new Private())
170{
171}
QScopedPointer< Private > m_d
KisPlaybackEngine(QObject *parent=nullptr)

◆ ~KisPlaybackEngineQT()

KisPlaybackEngineQT::~KisPlaybackEngineQT ( )

Definition at line 173 of file KisPlaybackEngineQT.cpp.

174{
175}

Member Function Documentation

◆ activeFramesPerSecond()

boost::optional< int64_t > KisPlaybackEngineQT::activeFramesPerSecond ( ) const

Definition at line 201 of file KisPlaybackEngineQT.cpp.

202{
203 if (activeCanvas()) {
205 } else {
206 return boost::none;
207 }
208}
KisImageWSP image() const
KisImageAnimationInterface * animationInterface() const
class KisCanvas2 * activeCanvas() const

References KisPlaybackEngine::activeCanvas(), KisImage::animationInterface(), KisImageAnimationInterface::framerate(), and KisCanvas2::image().

◆ isMute()

bool KisPlaybackEngineQT::isMute ( )
inlineoverridevirtual

Implements KisPlaybackEngine.

Definition at line 38 of file KisPlaybackEngineQT.h.

38{ return true; }

◆ playbackStatistics()

KisPlaybackEngine::PlaybackStats KisPlaybackEngineQT::playbackStatistics ( ) const
overridevirtual

Implements KisPlaybackEngine.

Definition at line 210 of file KisPlaybackEngineQT.cpp.

211{
213
214 if (activeCanvas()->animationState()->playbackState() == PLAYING) {
215 const int droppedFrames = m_d->measure.droppedFramesStat.rollingSum();
216 const int totalFrames =
217 m_d->measure.droppedFramesStat.rollingCount() +
218 droppedFrames;
219
220 stats.droppedFramesPortion = qreal(droppedFrames) / totalFrames;
221 stats.expectedFps = qreal(activeFramesPerSecond().get_value_or(24)) * m_d->driver->speed();
222
223 const qreal avgTimePerFrame = m_d->measure.averageTimePerFrame.rollingMeanSafe();
224 stats.realFps = !qFuzzyIsNull(avgTimePerFrame) ? 1000.0 / avgTimePerFrame : 0.0;
225 }
226
227 return stats;
228}
boost::optional< int64_t > activeFramesPerSecond() const
static bool qFuzzyIsNull(half h)

References KisPlaybackEngine::activeCanvas(), activeFramesPerSecond(), KisPlaybackEngine::PlaybackStats::droppedFramesPortion, KisPlaybackEngine::PlaybackStats::expectedFps, m_d, PLAYING, qFuzzyIsNull(), and KisPlaybackEngine::PlaybackStats::realFps.

◆ seek()

void KisPlaybackEngineQT::seek ( int frameIndex,
SeekOptionFlags flags = SEEK_FINALIZE | SEEK_PUSH_AUDIO )
overridevirtual

Implements KisPlaybackEngine.

Definition at line 177 of file KisPlaybackEngineQT.cpp.

178{
179 if (!activeCanvas())
180 return;
181
182 KIS_SAFE_ASSERT_RECOVER_RETURN(activeCanvas()->animationState());
183
185 KIS_SAFE_ASSERT_RECOVER_RETURN(displayProxy);
186
187 KIS_SAFE_ASSERT_RECOVER_RETURN(frameIndex >= 0);
188
189 if (displayProxy->activeFrame() != frameIndex || flags & SEEK_FINALIZE) {
190 displayProxy->displayFrame(frameIndex, flags & SEEK_FINALIZE);
191 }
192}
@ SEEK_FINALIZE
KisCanvasAnimationState * animationState() const
class KisFrameDisplayProxy * displayProxy()
The KisFrameDisplayProxy class sits between the KisCanvas (within its KisCanvasAnimationState) and it...
bool displayFrame(int frame, bool forceReproject)
Tell the DisplayProxy to show a new frame.
int activeFrame() const
Gets the active frame, the frame that is intended to be shown. This should always reflect the actual ...
#define KIS_SAFE_ASSERT_RECOVER_RETURN(cond)
Definition kis_assert.h:128

References KisPlaybackEngine::activeCanvas(), KisFrameDisplayProxy::activeFrame(), KisCanvas2::animationState(), KisFrameDisplayProxy::displayFrame(), KisCanvasAnimationState::displayProxy(), KIS_SAFE_ASSERT_RECOVER_RETURN, and SEEK_FINALIZE.

◆ setCanvas()

void KisPlaybackEngineQT::setCanvas ( KoCanvasBase * canvas)
overrideprotectedvirtual

Reimplemented from KisPlaybackEngine.

Definition at line 286 of file KisPlaybackEngineQT.cpp.

287{
288 KisCanvas2* canvas = dynamic_cast<KisCanvas2*>(p_canvas);
289
290 struct StopAndResume {
291 StopAndResume(KisPlaybackEngineQT* p_self)
292 : m_self(p_self) {
293 KIS_SAFE_ASSERT_RECOVER_RETURN(m_self->m_d->driver);
294
295 m_self->m_d->driver->setPlaybackState(PlaybackState::STOPPED);
296 }
297
298 ~StopAndResume() {
299 KIS_SAFE_ASSERT_RECOVER_RETURN(m_self->m_d->driver);
300
301 if (m_self->activeCanvas()) {
302 m_self->m_d->driver->setPlaybackState(m_self->activeCanvas()->animationState()->playbackState());
303 }
304 }
305
306 private:
307 KisPlaybackEngineQT* m_self;
308 };
309
310 if (activeCanvas() == canvas) {
311 return;
312 }
313
314 if (activeCanvas()) {
316
318
319 // Disconnect internal..
320 m_d->driver.data()->disconnect(this);
321
322 { // Disconnect old Image Anim Interface, prepare for new one..
323 auto image = activeCanvas()->image();
324 KisImageAnimationInterface* aniInterface = image ? image->animationInterface() : nullptr;
325 if (aniInterface) {
326 this->disconnect(image->animationInterface());
327 image->animationInterface()->disconnect(this);
328 }
329 }
330
331 { // Disconnect old display proxy, prepare for new one.
332 KisFrameDisplayProxy* displayProxy = animationState->displayProxy();
333
334 if (displayProxy) {
335 displayProxy->disconnect(this);
336 }
337 }
338
339 { // Disconnect old animation state, prepare for new one..
340 if (animationState) {
341 this->disconnect(animationState);
342 animationState->disconnect(this);
343 }
344 }
345 }
346
347 StopAndResume stopResume(this);
348
350
351 if (activeCanvas()) {
353 KIS_ASSERT(animationState);
354
356
357 { // Animation State Connections
358 connect(animationState, &KisCanvasAnimationState::sigPlaybackStateChanged, this, [this](PlaybackState state){
360
361 if (state == PLAYING) {
362 m_d->measure.reset();
363 }
364
365 m_d->driver->setPlaybackState(state);
366 });
367
368 connect(animationState, &KisCanvasAnimationState::sigPlaybackSpeedChanged, this, [this](qreal value){
370 m_d->driver->setSpeed(value);
371 });
372 m_d->driver->setSpeed(animationState->playbackSpeed());
373 }
374
375 { // Display proxy connections
376 KisFrameDisplayProxy* displayProxy = animationState->displayProxy();
377 KIS_ASSERT(displayProxy);
378 connect(displayProxy, &KisFrameDisplayProxy::sigFrameDisplayRefreshed, this, [this](){
379 m_d->measure.waitingForFrame = false;
380 });
381
382 connect(displayProxy, &KisFrameDisplayProxy::sigFrameRefreshSkipped, this, [this](){
383 m_d->measure.waitingForFrame = false;
384 });
385 }
386
387
388 { // Animation Interface Connections
389 auto image = activeCanvas()->image();
390 KIS_ASSERT(image);
391 KisImageAnimationInterface* aniInterface = image->animationInterface();
392 KIS_ASSERT(aniInterface);
393
394 connect(aniInterface, &KisImageAnimationInterface::sigFramerateChanged, this, [this](){
395 if (!activeCanvas())
396 return;
397
398 KisImageWSP img = activeCanvas()->image();
400 KisImageAnimationInterface* aniInterface = img->animationInterface();
401 KIS_SAFE_ASSERT_RECOVER_RETURN(aniInterface);
402
403 m_d->driver->setFramerate(aniInterface->framerate());
404 });
405
406 m_d->driver->setFramerate(aniInterface->framerate());
407 }
408
409 // Internal connections
410 connect(m_d->driver.data(), SIGNAL(throttledShowFrame()), this, SLOT(throttledDriverCallback()));
411
412 }
413}
float value(const T *src, size_t ch)
connect(this, SIGNAL(optionsChanged()), this, SLOT(saveOptions()))
The KisCanvasAnimationState class stores all of the canvas-specific animation state.
void sigPlaybackStateChanged(PlaybackState state)
void sigPlaybackSpeedChanged(qreal value)
void sigFrameRefreshSkipped()
sigFrameRefreshSkipped tracks whether asynchronous "slow" refreshes are skipped due to the frame bein...
void sigFrameDisplayRefreshed()
The KisPlaybackEngineQT class is an implementation of KisPlaybackEngine that drives animation playbac...
void throttledDriverCallback()
throttledDriverCallback handles signals from the internal driver that drives playback within this eng...
virtual void setCanvas(KoCanvasBase *p_canvas) override
#define KIS_ASSERT(cond)
Definition kis_assert.h:33

References KisPlaybackEngine::activeCanvas(), KisImage::animationInterface(), KisCanvas2::animationState(), connect(), KisCanvasAnimationState::displayProxy(), KisImageAnimationInterface::framerate(), KisCanvas2::image(), KIS_ASSERT, KIS_SAFE_ASSERT_RECOVER_RETURN, m_d, KisCanvasAnimationState::playbackSpeed(), PLAYING, KisPlaybackEngine::setCanvas(), KisFrameDisplayProxy::sigFrameDisplayRefreshed(), KisImageAnimationInterface::sigFramerateChanged(), KisFrameDisplayProxy::sigFrameRefreshSkipped(), KisCanvasAnimationState::sigPlaybackSpeedChanged(), KisCanvasAnimationState::sigPlaybackStateChanged(), STOPPED, throttledDriverCallback(), and value().

◆ setDropFramesMode()

void KisPlaybackEngineQT::setDropFramesMode ( bool value)
overridevirtual

Reimplemented from KisPlaybackEngine.

Definition at line 194 of file KisPlaybackEngineQT.cpp.

195{
198 m_d->driver->setDropFrames(value);
199}
virtual void setDropFramesMode(bool value)

References KIS_SAFE_ASSERT_RECOVER_RETURN, m_d, KisPlaybackEngine::setDropFramesMode(), and value().

◆ setMute()

void KisPlaybackEngineQT::setMute ( bool )
inlineoverridevirtual

Implements KisPlaybackEngine.

Definition at line 37 of file KisPlaybackEngineQT.h.

37{}

◆ supportsAudio()

bool KisPlaybackEngineQT::supportsAudio ( )
inlineoverridevirtual

Implements KisPlaybackEngine.

Definition at line 40 of file KisPlaybackEngineQT.h.

40{return false;}

◆ supportsVariablePlaybackSpeed()

bool KisPlaybackEngineQT::supportsVariablePlaybackSpeed ( )
inlineoverridevirtual

Implements KisPlaybackEngine.

Definition at line 41 of file KisPlaybackEngineQT.h.

41{ return true; }

◆ throttledDriverCallback

void KisPlaybackEngineQT::throttledDriverCallback ( )
protectedslot

throttledDriverCallback handles signals from the internal driver that drives playback within this engine. It will either increment frame time, wrapping within bounds, and communicate with KisFrameDisplayProxy or use the driver's desired time to control which frame is visible...

Definition at line 230 of file KisPlaybackEngineQT.cpp.

231{
233
234 KIS_SAFE_ASSERT_RECOVER_RETURN(activeCanvas()->animationState());
235 KIS_SAFE_ASSERT_RECOVER_RETURN(activeCanvas()->animationState()->playbackState() == PLAYING);
236
238 KIS_SAFE_ASSERT_RECOVER_RETURN(displayProxy);
239
242 KIS_SAFE_ASSERT_RECOVER_RETURN(animInterface);
243
244 // If we're waiting for each frame, then we delay our callback.
245 if (m_d->measure.waitingForFrame) {
246 // Without drop frames on, we need to factor out time that we're waiting
247 // for a frame from our time
248 return;
249 }
250
251 const int currentFrame = displayProxy->activeFrame();
252 const int startFrame = animInterface->activePlaybackRange().start();
253 const int endFrame = animInterface->activePlaybackRange().end();
254
255 const int timeSinceLastFrame = m_d->measure.timeSinceLastFrame.restart();
256 const int timePerFrame = qRound(1000.0 / qreal(activeFramesPerSecond().get_value_or(24)) / m_d->driver->speed());
257 m_d->measure.averageTimePerFrame(timeSinceLastFrame);
258
259
260 // Drop frames logic...
261 int extraFrames = 0;
262 if (m_d->driver->dropFrames()) {
263 const int offset = timeSinceLastFrame - timePerFrame;
264 extraFrames = qMax(0, offset) / timePerFrame;
265 }
266
267 m_d->measure.droppedFramesStat(extraFrames);
268
269 { // just advance the frame ourselves based on the displayProxy's active frame.
270 int targetFrame = currentFrame + 1 + extraFrames;
271
272 targetFrame = frameWrap(targetFrame, startFrame, endFrame);
273
274 if (currentFrame != targetFrame) {
275 // We only wait when drop frames is enabled.
276 m_d->measure.waitingForFrame = !m_d->driver->dropFrames();
277
278 bool neededRefresh = displayProxy->displayFrame(targetFrame, false);
279
280 // If we didn't need to refresh, we just continue as usual.
281 m_d->measure.waitingForFrame &= neededRefresh;
282 }
283 }
284}
const KisTimeSpan & activePlaybackRange() const
activePlaybackRange
int frameWrap(int frame, int startFrame, int endFrame)
int start() const
int end() const

References KisPlaybackEngine::activeCanvas(), KisFrameDisplayProxy::activeFrame(), activeFramesPerSecond(), KisImageAnimationInterface::activePlaybackRange(), KisImage::animationInterface(), KisCanvas2::animationState(), KisFrameDisplayProxy::displayFrame(), KisCanvasAnimationState::displayProxy(), KisTimeSpan::end(), KisPlaybackEngine::frameWrap(), KisCanvas2::image(), KIS_SAFE_ASSERT_RECOVER_RETURN, m_d, PLAYING, and KisTimeSpan::start().

◆ unsetCanvas()

void KisPlaybackEngineQT::unsetCanvas ( )
overrideprotectedvirtual

Reimplemented from KisPlaybackEngine.

Definition at line 415 of file KisPlaybackEngineQT.cpp.

416{
417 setCanvas(nullptr);
418}
void setCanvas(KoCanvasBase *canvas) override

References setCanvas().

Member Data Documentation

◆ m_d

QScopedPointer<Private> KisPlaybackEngineQT::m_d
private

Definition at line 65 of file KisPlaybackEngineQT.h.


The documentation for this class was generated from the following files: