diff --git a/app/codec/decoder.cpp b/app/codec/decoder.cpp index 0eebf8055..d208f80da 100644 --- a/app/codec/decoder.cpp +++ b/app/codec/decoder.cpp @@ -86,7 +86,7 @@ bool Decoder::Open(const CodecStream &stream) } } -TexturePtr Decoder::RetrieveVideo(Renderer *renderer, const rational &timecode, const RetrieveVideoParams ÷r, const QAtomicInt *cancelled) +TexturePtr Decoder::RetrieveVideo(Renderer *renderer, const rational &timecode, const RetrieveVideoParams ÷r, CancelAtom *cancelled) { QMutexLocker locker(&mutex_); @@ -102,7 +102,7 @@ TexturePtr Decoder::RetrieveVideo(Renderer *renderer, const rational &timecode, return nullptr; } - if (cancelled && *cancelled) { + if (cancelled && cancelled->IsCancelled()) { return nullptr; } @@ -160,7 +160,7 @@ void Decoder::Close() } } -bool Decoder::ConformAudio(const QVector &output_filenames, const AudioParams ¶ms, const QAtomicInt *cancelled) +bool Decoder::ConformAudio(const QVector &output_filenames, const AudioParams ¶ms, CancelAtom *cancelled) { return ConformAudioInternal(output_filenames, params, cancelled); } @@ -264,7 +264,7 @@ int64_t Decoder::GetImageSequenceIndex(const QString &filename) return number_only.toLongLong(); } -TexturePtr Decoder::RetrieveVideoInternal(Renderer *renderer, const rational &timecode, const RetrieveVideoParams ÷r, const QAtomicInt *cancelled) +TexturePtr Decoder::RetrieveVideoInternal(Renderer *renderer, const rational &timecode, const RetrieveVideoParams ÷r, CancelAtom *cancelled) { Q_UNUSED(timecode) Q_UNUSED(divider) @@ -272,7 +272,7 @@ TexturePtr Decoder::RetrieveVideoInternal(Renderer *renderer, const rational &ti return nullptr; } -bool Decoder::ConformAudioInternal(const QVector &filenames, const AudioParams ¶ms, const QAtomicInt* cancelled) +bool Decoder::ConformAudioInternal(const QVector &filenames, const AudioParams ¶ms, CancelAtom *cancelled) { Q_UNUSED(filenames) Q_UNUSED(cancelled) diff --git a/app/codec/decoder.h b/app/codec/decoder.h index 99fa74428..dff4cdb40 100644 --- a/app/codec/decoder.h +++ b/app/codec/decoder.h @@ -192,7 +192,7 @@ public: * * This function is thread safe and can only run while the decoder is open. \see Open() */ - TexturePtr RetrieveVideo(Renderer *renderer, const rational& timecode, const RetrieveVideoParams& params, const QAtomicInt *cancelled = nullptr); + TexturePtr RetrieveVideo(Renderer *renderer, const rational& timecode, const RetrieveVideoParams& params, CancelAtom *cancelled = nullptr); enum RetrieveAudioStatus { kInvalid = -1, @@ -227,7 +227,7 @@ public: * * This function is re-entrant. */ - virtual FootageDescription Probe(const QString& filename, const QAtomicInt* cancelled) const = 0; + virtual FootageDescription Probe(const QString& filename, CancelAtom *cancelled) const = 0; /** * @brief Closes media/deallocates memory @@ -239,7 +239,7 @@ public: /** * @brief Conform audio stream */ - bool ConformAudio(const QVector &output_filenames, const AudioParams ¶ms, const QAtomicInt *cancelled = nullptr); + bool ConformAudio(const QVector &output_filenames, const AudioParams ¶ms, CancelAtom *cancelled = nullptr); /** * @brief Create a Decoder instance using a Decoder ID @@ -287,9 +287,9 @@ protected: * Sub-classes must override this function IF they support video. Function is already mutexed * so sub-classes don't need to worry about thread safety. */ - virtual TexturePtr RetrieveVideoInternal(Renderer *renderer, const rational& timecode, const RetrieveVideoParams& params, const QAtomicInt *cancelled); + virtual TexturePtr RetrieveVideoInternal(Renderer *renderer, const rational& timecode, const RetrieveVideoParams& params, CancelAtom *cancelled); - virtual bool ConformAudioInternal(const QVector& filenames, const AudioParams ¶ms, const QAtomicInt* cancelled); + virtual bool ConformAudioInternal(const QVector& filenames, const AudioParams ¶ms, CancelAtom *cancelled); void SignalProcessingProgress(int64_t ts, int64_t duration); diff --git a/app/codec/ffmpeg/ffmpegdecoder.cpp b/app/codec/ffmpeg/ffmpegdecoder.cpp index bfd53c4f0..7469408c7 100644 --- a/app/codec/ffmpeg/ffmpegdecoder.cpp +++ b/app/codec/ffmpeg/ffmpegdecoder.cpp @@ -141,10 +141,10 @@ bool FFmpegDecoder::OpenInternal() return output_frame; }*/ -TexturePtr FFmpegDecoder::RetrieveVideoInternal(Renderer *renderer, const rational &timecode, const RetrieveVideoParams ¶ms, const QAtomicInt *cancelled) +TexturePtr FFmpegDecoder::RetrieveVideoInternal(Renderer *renderer, const rational &timecode, const RetrieveVideoParams ¶ms, CancelAtom *cancelled) { if (AVFramePtr f = RetrieveFrame(timecode, cancelled)) { - if (cancelled && *cancelled) { + if (cancelled && cancelled->IsCancelled()) { return nullptr; } @@ -289,7 +289,7 @@ QString FFmpegDecoder::id() const return QStringLiteral("ffmpeg"); } -FootageDescription FFmpegDecoder::Probe(const QString &filename, const QAtomicInt *cancelled) const +FootageDescription FFmpegDecoder::Probe(const QString &filename, CancelAtom *cancelled) const { // Return value FootageDescription desc(id()); @@ -514,7 +514,7 @@ QString FFmpegDecoder::FFmpegError(int error_code) return QStringLiteral("%1 %2").arg(QString::number(error_code), err); } -bool FFmpegDecoder::ConformAudioInternal(const QVector &filenames, const AudioParams ¶ms, const QAtomicInt *cancelled) +bool FFmpegDecoder::ConformAudioInternal(const QVector &filenames, const AudioParams ¶ms, CancelAtom *cancelled) { // Iterate through each audio frame and extract the PCM data @@ -564,7 +564,7 @@ bool FFmpegDecoder::ConformAudioInternal(const QVector &filenames, cons while (true) { // Check if we have a `cancelled` ptr and its value - if (cancelled && *cancelled) { + if (cancelled && cancelled->IsCancelled()) { break; } @@ -744,7 +744,7 @@ void FFmpegDecoder::ClearFrameCache() } } -AVFramePtr FFmpegDecoder::RetrieveFrame(const rational& time, const QAtomicInt *cancelled) +AVFramePtr FFmpegDecoder::RetrieveFrame(const rational& time, CancelAtom *cancelled) { int64_t target_ts = GetTimeInTimebaseUnits(time, instance_.avstream()->time_base, instance_.avstream()->start_time); @@ -782,7 +782,7 @@ AVFramePtr FFmpegDecoder::RetrieveFrame(const rational& time, const QAtomicInt * while (true) { // Break out of loop if we've cancelled - if (cancelled && *cancelled) { + if (cancelled && cancelled->IsCancelled()) { break; } @@ -793,7 +793,7 @@ AVFramePtr FFmpegDecoder::RetrieveFrame(const rational& time, const QAtomicInt * // Pull from the decoder ret = instance_.GetFrame(working_packet_, filtered.get()); - if (cancelled && *cancelled) { + if (cancelled && cancelled->IsCancelled()) { break; } diff --git a/app/codec/ffmpeg/ffmpegdecoder.h b/app/codec/ffmpeg/ffmpegdecoder.h index 4e51f496f..1c0d25bb8 100644 --- a/app/codec/ffmpeg/ffmpegdecoder.h +++ b/app/codec/ffmpeg/ffmpegdecoder.h @@ -31,7 +31,6 @@ extern "C" { #include } -#include #include #include #include @@ -64,12 +63,12 @@ public: virtual bool SupportsVideo() override{return true;} virtual bool SupportsAudio() override{return true;} - virtual FootageDescription Probe(const QString &filename, const QAtomicInt *cancelled) const override; + virtual FootageDescription Probe(const QString &filename, CancelAtom *cancelled) const override; protected: virtual bool OpenInternal() override; - virtual TexturePtr RetrieveVideoInternal(Renderer *renderer, const rational& timecode, const RetrieveVideoParams& params, const QAtomicInt *cancelled) override; - virtual bool ConformAudioInternal(const QVector& filenames, const AudioParams ¶ms, const QAtomicInt* cancelled) override; + virtual TexturePtr RetrieveVideoInternal(Renderer *renderer, const rational& timecode, const RetrieveVideoParams& params, CancelAtom *cancelled) override; + virtual bool ConformAudioInternal(const QVector& filenames, const AudioParams ¶ms, CancelAtom *cancelled) override; virtual void CloseInternal() override; private: @@ -151,7 +150,7 @@ private: void ClearFrameCache(); - AVFramePtr RetrieveFrame(const rational &time, const QAtomicInt *cancelled); + AVFramePtr RetrieveFrame(const rational &time, CancelAtom *cancelled); void RemoveFirstFrame(); diff --git a/app/codec/oiio/oiiodecoder.cpp b/app/codec/oiio/oiiodecoder.cpp index 9eea81d18..e9a84ca28 100644 --- a/app/codec/oiio/oiiodecoder.cpp +++ b/app/codec/oiio/oiiodecoder.cpp @@ -45,7 +45,7 @@ QString OIIODecoder::id() const return QStringLiteral("oiio"); } -FootageDescription OIIODecoder::Probe(const QString &filename, const QAtomicInt* cancelled) const +FootageDescription OIIODecoder::Probe(const QString &filename, CancelAtom *cancelled) const { Q_UNUSED(cancelled) @@ -116,7 +116,7 @@ bool OIIODecoder::OpenInternal() return OpenImageHandler(stream().filename(), stream().stream()); } -TexturePtr OIIODecoder::RetrieveVideoInternal(Renderer *renderer, const rational &timecode, const RetrieveVideoParams ¶ms, const QAtomicInt *cancelled) +TexturePtr OIIODecoder::RetrieveVideoInternal(Renderer *renderer, const rational &timecode, const RetrieveVideoParams ¶ms, CancelAtom *cancelled) { Q_UNUSED(timecode) Q_UNUSED(cancelled) diff --git a/app/codec/oiio/oiiodecoder.h b/app/codec/oiio/oiiodecoder.h index 5233678af..3cc894eba 100644 --- a/app/codec/oiio/oiiodecoder.h +++ b/app/codec/oiio/oiiodecoder.h @@ -40,11 +40,11 @@ public: virtual bool SupportsVideo() override{return true;} - virtual FootageDescription Probe(const QString& filename, const QAtomicInt* cancelled) const override; + virtual FootageDescription Probe(const QString& filename, CancelAtom *cancelled) const override; protected: virtual bool OpenInternal() override; - virtual TexturePtr RetrieveVideoInternal(Renderer *renderer, const rational& timecode, const RetrieveVideoParams& params, const QAtomicInt *cancelled) override; + virtual TexturePtr RetrieveVideoInternal(Renderer *renderer, const rational& timecode, const RetrieveVideoParams& params, CancelAtom *cancelled) override; virtual void CloseInternal() override; private: diff --git a/app/common/CMakeLists.txt b/app/common/CMakeLists.txt index b4bdea348..0b7ff983a 100644 --- a/app/common/CMakeLists.txt +++ b/app/common/CMakeLists.txt @@ -55,8 +55,6 @@ set(OLIVE_SOURCES common/ratiodialog.h common/rational.cpp common/rational.h - common/threadedobject.cpp - common/threadedobject.h common/threadsafemap.h common/timecodefunctions.cpp common/timecodefunctions.h diff --git a/app/common/cancelableobject.h b/app/common/cancelableobject.h index d7a1fe5d8..eef63d375 100644 --- a/app/common/cancelableobject.h +++ b/app/common/cancelableobject.h @@ -21,35 +21,38 @@ #ifndef CANCELABLEOBJECT_H #define CANCELABLEOBJECT_H -#include - #include "common/define.h" +#include "render/cancelatom.h" namespace olive { class CancelableObject { public: - CancelableObject() : - cancelled_(false) + CancelableObject() { } void Cancel() { - cancelled_ = true; + cancel_.Cancel(); CancelEvent(); } - const QAtomicInt& IsCancelled() const + CancelAtom *GetCancelAtom() { - return cancelled_; + return &cancel_; + } + + bool IsCancelled() + { + return cancel_.IsCancelled(); } protected: virtual void CancelEvent(){} private: - QAtomicInt cancelled_; + CancelAtom cancel_; }; diff --git a/app/common/threadedobject.cpp b/app/common/threadedobject.cpp deleted file mode 100644 index fccb2cd4d..000000000 --- a/app/common/threadedobject.cpp +++ /dev/null @@ -1,57 +0,0 @@ -/*** - - Olive - Non-Linear Video Editor - Copyright (C) 2022 Olive Team - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . - -***/ - -#include "threadedobject.h" - -namespace olive { - -void ThreadedObject::LockDeletes() -{ - threadobj_delete_lock_++; -} - -void ThreadedObject::UnlockDeletes() -{ - Q_ASSERT(AreDeletesLocked()); - - threadobj_delete_lock_--; -} - -bool ThreadedObject::AreDeletesLocked() -{ - return (threadobj_delete_lock_ > 0); -} - -void ThreadedObject::LockMutex() -{ - threadobj_main_lock_.lock(); -} - -void ThreadedObject::UnlockMutex() -{ - threadobj_main_lock_.unlock(); -} - -bool ThreadedObject::TryLockMutex(int timeout) -{ - return threadobj_main_lock_.tryLock(timeout); -} - -} diff --git a/app/common/threadedobject.h b/app/common/threadedobject.h deleted file mode 100644 index c42b4faa5..000000000 --- a/app/common/threadedobject.h +++ /dev/null @@ -1,50 +0,0 @@ -/*** - - Olive - Non-Linear Video Editor - Copyright (C) 2022 Olive Team - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . - -***/ - -#ifndef THREADEDOBJECT_H -#define THREADEDOBJECT_H - -#include - -#include "common/define.h" - -namespace olive { - -class ThreadedObject -{ -public: - - void LockMutex(); - void UnlockMutex(); - bool TryLockMutex(int timeout = 0); - - void LockDeletes(); - void UnlockDeletes(); - bool AreDeletesLocked(); - -private: - QMutex threadobj_main_lock_; - - QAtomicInt threadobj_delete_lock_; -}; - -} - -#endif // THREADEDOBJECT_H diff --git a/app/node/project/footage/footage.h b/app/node/project/footage/footage.h index 43e5f80c7..6b801972f 100644 --- a/app/node/project/footage/footage.h +++ b/app/node/project/footage/footage.h @@ -28,6 +28,7 @@ #include "footagedescription.h" #include "node/output/viewer/viewer.h" #include "render/audioparams.h" +#include "render/cancelatom.h" #include "render/videoparams.h" namespace olive { @@ -141,7 +142,7 @@ public: */ void set_timestamp(const qint64 &t); - void SetCancelPointer(const QAtomicInt* c) + void SetCancelPointer(CancelAtom *c) { cancelled_ = c; } @@ -232,7 +233,7 @@ private: bool valid_; - const QAtomicInt* cancelled_; + CancelAtom *cancelled_; private slots: void CheckFootage(); diff --git a/app/node/traverser.cpp b/app/node/traverser.cpp index ed7aae25d..a2a38a3be 100644 --- a/app/node/traverser.cpp +++ b/app/node/traverser.cpp @@ -260,7 +260,6 @@ NodeValueTable NodeTraverser::ProcessInput(const Node* node, const QString& inpu NodeTraverser::NodeTraverser() : cancel_(nullptr), - heard_cancel_(false), transform_(nullptr) { } diff --git a/app/node/traverser.h b/app/node/traverser.h index 524fc8337..1c0fbe9da 100644 --- a/app/node/traverser.h +++ b/app/node/traverser.h @@ -26,6 +26,7 @@ #include "codec/decoder.h" #include "common/cancelableobject.h" #include "node/output/track/track.h" +#include "render/cancelatom.h" #include "render/job/footagejob.h" #include "render/job/colortransformjob.h" #include "value.h" @@ -130,24 +131,16 @@ protected: bool IsCancelled() { - bool c = cancel_ && *cancel_; - if (c) { - heard_cancel_ = true; - } - return c; + return cancel_ && cancel_->IsCancelled(); } - bool HeardCancel() const { return heard_cancel_; } - - const QAtomicInt *GetCancelPointer() const + bool HeardCancel() const { - return cancel_; + return cancel_ && cancel_->HeardCancel(); } - void SetCancelPointer(const QAtomicInt *cancel) - { - cancel_ = cancel; - } + CancelAtom *GetCancelPointer() const { return cancel_; } + void SetCancelPointer(CancelAtom *cancel) { cancel_ = cancel; } void ResolveJobs(NodeValue &value, const TimeRange &range); @@ -165,8 +158,7 @@ private: AudioParams audio_params_; - const QAtomicInt *cancel_; - bool heard_cancel_; + CancelAtom *cancel_; const Node *transform_start_; const Node *transform_now_; diff --git a/app/render/CMakeLists.txt b/app/render/CMakeLists.txt index d8a9a9a22..dcde3f3ed 100644 --- a/app/render/CMakeLists.txt +++ b/app/render/CMakeLists.txt @@ -24,6 +24,7 @@ set(OLIVE_SOURCES render/audioparams.h render/audioplaybackcache.cpp render/audioplaybackcache.h + render/cancelatom.h render/color.cpp render/color.h render/colorprocessor.cpp diff --git a/app/render/cancelatom.h b/app/render/cancelatom.h new file mode 100644 index 000000000..d4db43c1c --- /dev/null +++ b/app/render/cancelatom.h @@ -0,0 +1,48 @@ +#ifndef CANCELATOM_H +#define CANCELATOM_H + +#include + +namespace olive { + +class CancelAtom +{ +public: + CancelAtom() : + cancelled_(false), + heard_(false) + {} + + bool IsCancelled() + { + QMutexLocker locker(&mutex_); + if (cancelled_) { + heard_ = true; + } + return cancelled_; + } + + void Cancel() + { + QMutexLocker locker(&mutex_); + cancelled_ = true; + } + + bool HeardCancel() + { + QMutexLocker locker(&mutex_); + return heard_; + } + +private: + QMutex mutex_; + + bool cancelled_; + + bool heard_; + +}; + +} + +#endif // CANCELATOM_H diff --git a/app/render/renderprocessor.cpp b/app/render/renderprocessor.cpp index 5b60436f8..400f0984c 100644 --- a/app/render/renderprocessor.cpp +++ b/app/render/renderprocessor.cpp @@ -134,7 +134,7 @@ void RenderProcessor::Run() // Depending on the render ticket type, start a job RenderManager::TicketType type = ticket_->property("type").value(); - SetCancelPointer(&ticket_->IsCancelled()); + SetCancelPointer(ticket_->GetCancelAtom()); SetCacheVideoParams(ticket_->property("vparam").value()); SetCacheAudioParams(ticket_->property("aparam").value()); diff --git a/app/task/conform/conform.cpp b/app/task/conform/conform.cpp index a0cd5fe72..4c73ef770 100644 --- a/app/task/conform/conform.cpp +++ b/app/task/conform/conform.cpp @@ -42,7 +42,7 @@ bool ConformTask::Run() connect(decoder.get(), &Decoder::IndexProgress, this, &ConformTask::ProgressChanged); - bool ret = decoder->ConformAudio(output_filenames_, params_, &IsCancelled()); + bool ret = decoder->ConformAudio(output_filenames_, params_, GetCancelAtom()); decoder->Close();