From 729ceec03279b42c158aef1f3b6dd6b11a0593df Mon Sep 17 00:00:00 2001 From: Andrew Wason Date: Wed, 18 Oct 2023 09:47:16 -0400 Subject: [PATCH] refactor rendering --- mediafx/clip.cpp | 27 +++++++++++++++++++++++++++ mediafx/clip.h | 5 +++++ mediafx/mediafx.cpp | 23 +++++++++++++---------- mediafx/mediafx.h | 8 ++++---- mediafx/visual_clip.cpp | 39 ++++++++++++++------------------------- mediafx/visual_clip.h | 5 ++--- 6 files changed, 65 insertions(+), 42 deletions(-) diff --git a/mediafx/clip.cpp b/mediafx/clip.cpp index ca32f89..994d5ab 100644 --- a/mediafx/clip.cpp +++ b/mediafx/clip.cpp @@ -37,6 +37,33 @@ void Clip::setClipEnd(qint64 clipEnd) } } +bool Clip::render(const QMediaTimeRange::Interval& globalTime) +{ + // Already rendered for this time + if (currentGlobalTime() == globalTime) + return true; + + qint64 duration = globalTime.end() - globalTime.start(); + if (nextClipTime().end() == -1) { + setNextClipTime(QMediaTimeRange::Interval(clipStart(), clipStart() + duration)); + } + if (active() && clipTimeRange().contains(nextClipTime().start())) { + if (renderClip(globalTime)) { + setCurrentGlobalTime(globalTime); + setNextClipTime(nextClipTime().translated(duration)); + return true; + } else { + return false; + } + } else if (clipEnd() < nextClipTime().start()) { + stop(); + return false; + } else { + setActive(false); + return false; + } +} + void Clip::stop() { setNextClipTime(QMediaTimeRange::Interval(clipStart(), -1)); diff --git a/mediafx/clip.h b/mediafx/clip.h index c7e61c9..3a24405 100644 --- a/mediafx/clip.h +++ b/mediafx/clip.h @@ -41,6 +41,8 @@ class Clip : public QObject { qint64 clipEnd() const { return m_clipSegment.end(); }; void setClipEnd(qint64); + bool render(const QMediaTimeRange::Interval& globalTime); + signals: void clipStartChanged(); void clipEndChanged(); @@ -54,9 +56,12 @@ class Clip : public QObject { void setCurrentGlobalTime(const QMediaTimeRange::Interval& currentTime) { m_currentGlobalTime = currentTime; }; virtual void setActive(bool active) = 0; + virtual bool active() = 0; virtual void loadMedia(const QUrl&) = 0; + virtual bool renderClip(const QMediaTimeRange::Interval& globalTime) = 0; + QMediaTimeRange::Interval nextClipTime() const { return m_nextClipTime; }; virtual void stop(); diff --git a/mediafx/mediafx.cpp b/mediafx/mediafx.cpp index a12fcae..ca178ee 100644 --- a/mediafx/mediafx.cpp +++ b/mediafx/mediafx.cpp @@ -3,7 +3,7 @@ // found in the LICENSE file. #include "mediafx.h" -#include "visual_clip.h" +#include "clip.h" #include #include #include @@ -23,13 +23,15 @@ MediaFX::MediaFX() MediaFX::typeId = qmlTypeId("stream.mediafx", 254, 254, "MediaFX"); } -void MediaFX::registerVisualClip(VisualClip* clip) +void MediaFX::registerClip(Clip* clip) { - if (clip && !activeVisualClips.contains(clip)) { - activeVisualClips.append(clip); - // Ensure we don't have multiple clips simultaneously rendering to the same sink + if (clip && !activeClips.contains(clip)) { + activeClips.append(clip); +#if 0 // XXX how should we deal with this? same issue for main audio, don't want to mix audio buffers from different Clips +//XXX move this into Clip subclasses setActive, so they can query other activeClips and check? + // Ensure we don't have multiple clips simultaneously rendering to the same sink QSet set; - for (const auto clip : activeVisualClips) { + for (const auto clip : activeClips) { for (const auto sink : clip->videoSinks()) { if (set.contains(sink)) { qWarning() << "Warning: duplicate QVideoSink found on " << clip; @@ -38,12 +40,13 @@ void MediaFX::registerVisualClip(VisualClip* clip) set.insert(sink); } } +#endif } } -void MediaFX::unregisterVisualClip(VisualClip* clip) +void MediaFX::unregisterClip(Clip* clip) { - activeVisualClips.removeOne(clip); + activeClips.removeOne(clip); } // XXX need to signal frame time so QML can react (how will QML normalize for transitions etc.?) @@ -51,8 +54,8 @@ void MediaFX::unregisterVisualClip(VisualClip* clip) bool MediaFX::renderVideoFrame(const QMediaTimeRange::Interval& frameTimeRange) { bool rendered = true; - for (auto clip : activeVisualClips) { - rendered = rendered && clip->renderVideoFrame(frameTimeRange); + for (auto clip : activeClips) { + rendered = rendered && clip->render(frameTimeRange); } return rendered; } \ No newline at end of file diff --git a/mediafx/mediafx.h b/mediafx/mediafx.h index 6160bf7..52f61f5 100644 --- a/mediafx/mediafx.h +++ b/mediafx/mediafx.h @@ -8,7 +8,7 @@ #include #include #include -class VisualClip; +class Clip; class MediaFX : public QObject { Q_OBJECT @@ -19,11 +19,11 @@ class MediaFX : public QObject { MediaFX(); static int typeId; - void registerVisualClip(VisualClip* clip); - void unregisterVisualClip(VisualClip* clip); + void registerClip(Clip* clip); + void unregisterClip(Clip* clip); bool renderVideoFrame(const QMediaTimeRange::Interval& frameTimeRange); private: - QList activeVisualClips; + QList activeClips; }; \ No newline at end of file diff --git a/mediafx/visual_clip.cpp b/mediafx/visual_clip.cpp index 6398242..98d9ffe 100644 --- a/mediafx/visual_clip.cpp +++ b/mediafx/visual_clip.cpp @@ -19,43 +19,32 @@ void VisualClip::setVideoSinks(const QList& videoSinks) } } +bool VisualClip::active() +{ + return !m_videoSinks.isEmpty(); +} + void VisualClip::setActive(bool active) { auto mediaFX = qmlEngine(this)->singletonInstance(MediaFX::typeId); if (active) { - mediaFX->registerVisualClip(this); + mediaFX->registerClip(this); } else { - mediaFX->unregisterVisualClip(this); + mediaFX->unregisterClip(this); m_videoSinks.clear(); } } -bool VisualClip::renderVideoFrame(const QMediaTimeRange::Interval& globalTime) +bool VisualClip::renderClip(const QMediaTimeRange::Interval& globalTime) { - if (currentGlobalTime() == globalTime) - return true; - qint64 duration = globalTime.end() - globalTime.start(); - if (nextClipTime().end() == -1) { - setNextClipTime(QMediaTimeRange::Interval(clipStart(), clipStart() + duration)); - } - if (!videoSinks().isEmpty() && clipTimeRange().contains(nextClipTime().start())) { - if (!prepareNextVideoFrame()) - return false; - m_currentVideoFrame.setStartTime(globalTime.start()); - m_currentVideoFrame.setEndTime(globalTime.end()); - for (auto videoSink : videoSinks()) { - videoSink->setVideoFrame(m_currentVideoFrame); - } - setCurrentGlobalTime(globalTime); - setNextClipTime(nextClipTime().translated(duration)); - return true; - } else if (clipEnd() < nextClipTime().start()) { - stop(); - return false; - } else { - setActive(false); + if (!prepareNextVideoFrame()) return false; + m_currentVideoFrame.setStartTime(globalTime.start()); + m_currentVideoFrame.setEndTime(globalTime.end()); + for (auto videoSink : videoSinks()) { + videoSink->setVideoFrame(m_currentVideoFrame); } + return true; } void VisualClip::stop() diff --git a/mediafx/visual_clip.h b/mediafx/visual_clip.h index 356b306..c957e9b 100644 --- a/mediafx/visual_clip.h +++ b/mediafx/visual_clip.h @@ -24,13 +24,12 @@ class VisualClip : public Clip { QList videoSinks() const { return m_videoSinks; }; void setVideoSinks(const QList&); - bool renderVideoFrame(const QMediaTimeRange::Interval& globalTime); - protected: void setActive(bool active) override; + bool active() override; + bool renderClip(const QMediaTimeRange::Interval& globalTime) override; virtual bool prepareNextVideoFrame() = 0; - void setCurrentVideoFrame(const QVideoFrame& videoFrame) { m_currentVideoFrame = videoFrame; }; virtual void stop() override;